/***************************************************************************
*
Copyright 2013 CertiVox UK Ltd. *
*
This file is part of CertiVox MIRACL Crypto SDK. *
*
The CertiVox MIRACL 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 MIRACL 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 MIRACL Crypto SDK is distributed in the hope *
that it will be useful, but WITHOUT ANY WARRANTY; without even the *
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
See the GNU Affero General Public License for more details. *
*
* You should have received a copy of the GNU Affero General Public *
License along with CertiVox MIRACL Crypto SDK. *
If not, see . *
*
You can be released from the requirements of the license by purchasing *
a commercial license. Buying such a license is mandatory as soon as you *
develop commercial activities involving the CertiVox MIRACL Crypto SDK *
without disclosing the source code of your own applications, or shipping *
the CertiVox MIRACL Crypto SDK with a closed source product. *
*
***************************************************************************/
/*
* MIRACL-based implementation of the IEEE 1363 standard
* Version 1.6 July 2010
*
* NEW 1.1 - Elliptic curve points now stored in a single OCTET as recommended
* in P1363a. Such octets will be 2*fs+1 in length, where fs is
* the field size. If compression is used they may be fs+1
*
* NEW 1.2 - Auxiliary functions completely re-written
* More primitives and functions implemented
* New mirvar_mem function used for extra speed
*
* NEW 1.3 - Cryptographically strong RNG interface improved
*
* NEW 1.6 - Support for .NET applications. See below
*
* Implements most of the cryptographic primitives, message encoding methods,
* key derivation functions and auxiliary functions necessary for realising the
* recommended methods. Note that GF(p) and GF(2^m) Elliptic curves are
* treated seperately.
*
* See the IEEE 1363 documentation for details
* http://grouper.ieee.org/groups/1363/index.html
* This IS the documentation for this implementation. Each P1363 function
* has the same name, and same inputs/outputs as those described in the
* official 1363 documentation.
*
* The user is responsible for the initialisation and maintainance of
* "Octet strings" which store Cryptographic keys and application info.
* These octet strings store big numbers in binary, from MSB down to LSB
* NOTE:- Leading zeros can be suppressed! Use OCTET_PAD() to insert leading
* zeros to make an octet a particular length, e.g. 20 bytes, 160 bits.
*
* An instance of a Cryptographically Strong Random Number Generator
* must be created and initialised by the user with
* raw random data. This doesn't have to be high quality (e.g. mouse movement
* coordinates), but there must be enough of it for it to be unguessable.
* It is subsequently maintained internally by the system
* The secure random number generation method used is based on that described
* in ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf
*
* The above is the recommended approach.
* Alternatvely when generating a key pair a random number can be specified
* directly as a private key, and this internal system by-passed.
*
* Domain and Public/Private key data is stored in structures defined in
* p1363.h. The first parameter in each function is a pointer to a function
* which will be called during time-consuming calculations - e.g. a Windows
* message pump. Negative return values indicate an error - see p1363.h for
* definitions. Most common MIRACL errors are mapped to these values.
* Unlikely MIRACL errors are returned as -(1000+MEC), where MEC
* is the MIRACL Error Code (see miracl.h)
*
* quick start:-
* cl /O2 test1363.c p1363.c miracl.lib
*
* Recommended for use with a (32-bit) MIRACL library built
* from a mirdef.h file that looks something like this:-
*
* #define MIRACL 32
* #define MR_LITTLE_ENDIAN
* #define mr_utype int
* #define MR_IBITS 32
* #define MR_LBITS 32
* #define mr_unsign32 unsigned int
* #define MR_STRIPPED_DOWN
* #define MR_GENERIC_MT
* #define mr_dltype __int64
* #define mr_unsign64 unsigned __int64
* #define MAXBASE ((mr_small)1<<(MIRACL-1))
*
* Note that this is a multi-threaded build, ideal for a Cryptographic DLL
* The compiler may need a multithreaded flag set (/MT ??)
*
* The miracl instance variable ERCON is set to TRUE in each routine, so
* MIRACL does not attempt to report an error. Instead the variable ERNUM
* latches the last error, and if set causes each subsequent routine to
* "fall through".
*
* Octet strings are not tested for overflow. In fact overflow will not
* happen as octets will be truncated - so buffer overflow attacks against
* this code will not succeed. To avoid unintentional overflow its best to
* initialise the length of most octets to that recommended and returned by
* the XXX_DOMAIN_INIT() routines. Note however that elliptic curve point
* octets should be initialised to "twice this length plus 1" (or only "this
* length plus 1" if compression is used)
*
* A test driver main() function is provided in test1363.c to test all the
* functions, and to implement many of the recommended methods, ECDSA, IFSSA,
* IFSSR, DLSSR, DLSSR-PV and ECIES
*
* In Win32 MS C:-
* cl /O2 /MT test1363.c p1363.c miracl.lib /link /NODEFAULTLIB:libc.lib
* and run the executable
*
* test1363 ;
* test1363 -c ; uses EC point compression
* test1363 -p ; uses precomputation (window size = 8) for signature
* test1363 -c -p ; uses both precomputation and EC point compression
*
* To create a Windows P1363 DLL, compile as
* cl /O2 /W3 /MT /DMR_P1363_DLL /LD p1363.c miracl.lib /link /NODEFAULTLIB:libc.lib
* To run the test program to use the DLL, compile as
* cl /O2 /MT /DMR_P1363_DLL test1363.c p1363.lib
*
* In .NET MS C:-
* Build miracl library as described in managed.txt - but perhaps include
* #define MR_GENERIC_MT
* #define MR_STRIPPED_DOWN
*
* To create a DLL compile as
* cl /clr /O2 /DMR_P1363_DLL /LD /Tp p1363.c miracl.lib
* To run the test program to use the DLL, compile as
* cl /clr /O2 /DMR_P1363_DLL /Tp test1363.c p1363.lib
*
* Discrete Logarithm/GF(p) Elliptic Curve/GF(2^m) Elliptic Curve Domain
* details are read from the files common.dss, common.ecs and common2.ecs
* respectively. Suitable files are included in the standard MIRACL
* distribution. You can generate your own using for example the utilities
* dssetup.cpp, schoof.cpp and schoof2.cpp. But make sure that the group order
* in each case is at least 160-bits, or the demo may fail.
*
* Note that for a full 1363 implementation various simple message-encoding
* regimes must be also implemented, as described in the P1363 and P1363a
* documentation. Many of these are now implemented here. Also suitable hashing
* functions must be available. The SHA1/SHA256/SHA384 and SHA512 algorithms
* are recommended, and implemented in MIRACL
*
* Note that some of the message encoding functions can take input from a file
* rather than from a string. This is convenient for example if "signing" a
* large document. In these cases the parameters are typically "octet *x,FILE
* *fp", in which case either an OCTET string x can be specified OR a
* filename, but not both.
*
* Version 1.5
* Miracl STATIC (no-heap version) supported. However octets (which are often
* variable length) are still allocated from the heap by default. To allocate
* fixed size octets from the stack edit p1363.h and define OCTET_FROM_STACK_SIZE
* NOTE: Precomputation not directly supported in this mode
*
* NOTE: It would be typical to break this file up and just use the parts that are needed
* (For example if using Elliptic curve methods only, then the size of structures could be much smaller)
*
* NOTE: Certain methods employed in the IEEE-1363 may be subject to US patent protection.
* Check http://grouper.ieee.org/groups/1363/index.html for more details
*
*/
/* define this next to create Windows DLL */
/* #define MR_1363_DLL */
#ifdef MR_P1363_DLL
#define P1363_DLL
#endif
#include
#include
#include "p1363.h"
/* Hash IDs for supported EMSA3 hash functions. , */
static unsigned char SHA160ID[]={15,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14};
static unsigned char SHA256ID[]={19,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
static unsigned char SHA384ID[]={19,0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
static unsigned char SHA512ID[]={19,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
/* IDs for SHA1,RIPEMD,SHA256,SHA384 and SHA512 */
/* NOTE ripemd is not implemented */
static unsigned char sha_id[]={0x33,0x31,0x34,0x36,0x35};
/* Internal functions */
static long filelength(FILE *fp)
{ /* return file length in reasonably portable fashion */
long len;
fseek(fp,0,SEEK_END);
len=ftell(fp);
fseek(fp,0,SEEK_SET);
return len;
}
static void OS2FEP(_MIPD_ octet *s,big w)
{ /* internal:- converts from octet to big format */
bytes_to_big(_MIPP_ s->len,s->val,w);
}
static void convert_big_octet(_MIPD_ big w,octet *s)
{ /* internal:- converts from big integer to octet format */
s->len=(oltype)big_to_bytes(_MIPP_ 0,w,s->val,FALSE);
}
static void FE2OSP(_MIPD_ big w,int fsize,octet *s)
{ /* internal:- converts from big to field element format */
s->len=(oltype)big_to_bytes(_MIPP_ fsize,w,s->val,TRUE);
}
static void EC2OSP(_MIPD_ big x,big y,int cbit,BOOL compressed,int fsize,octet *s)
{ /* internal:- converts from (x,y) to octet string */
s->len=1;
if (compressed) s->val[0]=2+cbit;
else s->val[0]=6+cbit; /* hybrid */
s->len+=(oltype)big_to_bytes(_MIPP_ fsize,x,&(s->val[1]),TRUE);
if (!compressed) s->len+=(oltype)big_to_bytes(_MIPP_ fsize,y,&(s->val[fsize+1]),TRUE);
}
static BOOL OS2ECP(_MIPD_ octet *s,big x,big y,int fsize,int *bit)
{ /* converts from octet string to (x,y) point */
bytes_to_big(_MIPP_ fsize,&(s->val[1]),x);
if (s->val[0]&4)
{ /* uncompressed ..but don't put a y if not required */
if(y!=NULL) bytes_to_big(_MIPP_ fsize,&(s->val[fsize+1]),y);
return FALSE;
}
else
{ /* compressed */
*bit=s->val[0]&1;
return TRUE;
}
}
/* return output length of hash function in bytes, also hash function input
block size if desired */
static int hash_params(int hash_type,int *block)
{
switch (hash_type)
{
case SHA1:
if (block!=NULL) *block=64;
return 20;
case SHA256:
if (block!=NULL) *block=64;
return 32;
#ifdef mr_unsign64
case SHA384:
if (block!=NULL) *block=128;
return 48;
case SHA512:
if (block!=NULL) *block=128;
return 64;
#endif
default:
break;
}
return 0;
}
/*** Basic Octet string maintainance routines ***/
/* initialize an octet string */
/* make it impossible to write beyond max length */
P1363_API BOOL OCTET_INIT(octet *w,int bytes)
{
w->len=0;
w->max=bytes;
#ifndef OCTET_FROM_STACK_SIZE
w->val=(char *)malloc(bytes);
if (w->val!=NULL) return TRUE;
else return FALSE;
#else
return TRUE;
#endif
}
P1363_API void OCTET_INIT_FROM_ARRAY(octet *w,int bytes,char *array)
{
w->len=0;
w->max=bytes;
w->val=array;
}
/* clear an octet string */
P1363_API void OCTET_CLEAR(octet *w)
{
int i;
for (i=0;ilen;i++) w->val[i]=0;
w->len=0;
}
/* XOR m with all of x */
P1363_API void OCTET_XOR_BYTE(octet *x,int m)
{
int i;
for (i=0;ilen;i++) x->val[i]^=m;
}
/* XOR common bytes of x with y */
P1363_API void OCTET_XOR(octet *x,octet *y)
{ /* xor first x->len bytes of y */
int i;
for (i=0;ilen && ilen;i++)
{
y->val[i]^=x->val[i];
}
}
/* clear an octet */
P1363_API void OCTET_EMPTY(octet *w)
{
w->len=0;
}
/* copy an octet string - truncates if no room */
P1363_API void OCTET_COPY(octet *x,octet *y)
{
int i;
OCTET_CLEAR(y);
y->len=x->len;
if (y->len>y->max) y->len=y->max;
for (i=0;ilen;i++)
y->val[i]=x->val[i];
}
/* compare 2 octet strings.
* If x==y return TRUE, else return FALSE */
P1363_API BOOL OCTET_COMPARE(octet *x,octet *y)
{
int i;
if (x->len>y->len) return FALSE;
if (x->lenlen) return FALSE;
for (i=0;ilen;i++)
{
if (x->val[i]!=y->val[i]) return FALSE;
}
return TRUE;
}
/* check are first n bytes the same */
P1363_API BOOL OCTET_NCOMPARE(octet *x,octet *y,int n)
{
int i;
if (n>y->len || n>x->len) return FALSE;
for (i=0;ival[i]!=y->val[i]) return FALSE;
}
return TRUE;
}
/* Pads an octet with leading zeros - returns FALSE if not enough room */
P1363_API BOOL OCTET_PAD(octet *x,int len)
{
int i,d;
if (len>x->max || x->len>len) return FALSE;
if (len==x->len) return TRUE;
d=len - x->len;
for (i=len-1;i>=d;i--)
x->val[i]=x->val[i-d];
for (i=0;ival[i]=0;
x->len=(oltype)len;
return TRUE;
}
/* Shift octet to the left by n bytes. Leftmost bytes disappear */
P1363_API void OCTET_SHIFT_LEFT(octet *x,int n)
{
int i;
if (n>=x->len)
{
x->len=0;
return;
}
x->len-=n;
for (i=0;ilen;i++)
x->val[i]=x->val[i+n];
}
/* truncates x to n bytes and places the rest in y (if y is not NULL) */
P1363_API void OCTET_CHOP(octet *x,int n,octet *y)
{
int i;
if (n>=x->len)
{
if (y!=NULL) y->len=0;
return;
}
if (y!=NULL) y->len=x->len-n;
x->len=n;
if (y!=NULL)
{
for (i=0;ilen && imax;i++) y->val[i]=x->val[i+n];
}
}
/* Concatenates two octet strings */
P1363_API void OCTET_JOIN_OCTET(octet *x,octet *y)
{ /* y=y || x */
int i,j;
if (x==NULL) return;
for (i=0;ilen;i++)
{
j=y->len+i;
if (j>=y->max)
{
y->len=y->max;
return;
}
y->val[j]=x->val[i];
}
y->len+=x->len;
}
/* OCTET_JOIN_LONG primitive */
/* appends long x of length len bytes to OCTET string */
P1363_API void OCTET_JOIN_LONG(long x, int len,octet *y) {
int i,j,n;
n=y->len+len;
if (n>y->max || len<=0) return;
for (i=y->len;ival[i]=0;
y->len=n;
i=y->len;
while (x>0 && i>0)
{
i--;
y->val[i]=x%256;
x/=256;
}
}
/* Convert C string to octet format - truncates if no room */
P1363_API void OCTET_JOIN_STRING(char *s,octet *y)
{
int i,j;
i=y->len;
j=0;
while (s[j]!=0 && imax)
{
y->val[i]=s[j];
y->len++;
i++; j++;
}
}
/* Append binary string to octet - truncates if no room */
P1363_API void OCTET_JOIN_BYTES(char *b,int len,octet *y)
{
int i,j;
i=y->len;
for (j=0;jmax;j++)
{
y->val[i]=b[j];
y->len++;
i++;
}
}
/* Append byte to octet rep times */
P1363_API void OCTET_JOIN_BYTE(int ch,int rep,octet *y)
{
int i,j;
i=y->len;
for (j=0;jmax;j++)
{
y->val[i]=ch;
y->len++;
i++;
}
}
/* Copy len random bytes into octet */
P1363_API void OCTET_RAND(csprng *RNG,int len,octet *x)
{
int i;
if (len>x->max) len=x->max;
x->len=len;
for (i=0;ival[i]=strong_rng(RNG);
}
/* Output an octet string (Debug Only) */
P1363_API void OCTET_OUTPUT(octet *w)
{
int i;
unsigned char ch;
for (i=0;ilen;i++)
{
ch=w->val[i];
printf("%02x",ch);
}
printf("\n");
}
P1363_API void OCTET_PRINT_STRING(octet *w)
{
int i;
unsigned char ch;
for (i=0;ilen;i++)
{
ch=w->val[i];
printf("%c",ch);
}
}
/* Kill an octet string - Zeroise it for security */
P1363_API void OCTET_KILL(octet *w)
{
int i;
for (i=0;imax;i++) w->val[i]=0;
w->len=0;
w->max=0;
#ifndef OCTET_FROM_STACK_SIZE
free(w->val);
#endif
}
/*** P1363 Auxiliary Functions ***/
/* Internal - All Purpose Hash function */
/* Input is taken from
1. octet p
2. pointer to 32-bit number n
3. octet x
4. file fp - opened by calling program
5. octet e
in this order.
Returns TRUE if x and/or fp are empty
*/
static BOOL hash(octet *p,int *n,octet *x,FILE *fp,octet *e,int hash_type,octet *w)
{
BOOL result=TRUE;
int i,hlen,ch,c[4];
sha256 sh32;
#ifdef mr_unsign64
sha512 sh64;
#endif
char hh[MAX_HASH_BYTES];
if (n!=NULL)
{
c[0]=(*n>>24)&0xff;
c[1]=(*n>>16)&0xff;
c[2]=(*n>>8)&0xff;
c[3]=(*n)&0xff;
}
hlen=hash_params(hash_type,NULL);
if (hlen==0)
{
OCTET_EMPTY(w);
return result;
}
switch (hash_type)
{
case SHA1:
shs_init(&sh32);
if (p!=NULL)
for (i=0;ilen;i++) shs_process(&sh32,p->val[i]);
if (n!=NULL)
for (i=0;i<4;i++) shs_process(&sh32,c[i]);
if (x!=NULL)
for (i=0;ilen;i++)
{ shs_process(&sh32,x->val[i]); result=FALSE; }
if (fp!=NULL)
while ((ch=fgetc(fp))!=EOF)
{ shs_process(&sh32,ch); result=FALSE;}
if (e!=NULL)
for (i=0;ilen;i++) shs_process(&sh32,e->val[i]);
shs_hash(&sh32,hh);
break;
case SHA256:
shs256_init(&sh32);
if (p!=NULL)
for (i=0;ilen;i++) shs256_process(&sh32,p->val[i]);
if (n!=NULL)
for (i=0;i<4;i++) shs256_process(&sh32,c[i]);
if (x!=NULL)
for (i=0;ilen;i++)
{ shs256_process(&sh32,x->val[i]); result=FALSE; }
if (fp!=NULL)
while ((ch=fgetc(fp))!=EOF)
{ shs256_process(&sh32,ch); result=FALSE; }
if (e!=NULL)
for (i=0;ilen;i++) shs256_process(&sh32,e->val[i]);
shs256_hash(&sh32,hh);
break;
#ifdef mr_unsign64
case SHA384:
shs384_init(&sh64);
if (p!=NULL)
for (i=0;ilen;i++) shs384_process(&sh64,p->val[i]);
if (n!=NULL)
for (i=0;i<4;i++) shs384_process(&sh64,c[i]);
if (x!=NULL)
for (i=0;ilen;i++)
{ shs384_process(&sh64,x->val[i]); result=FALSE; }
if (fp!=NULL)
while ((ch=fgetc(fp))!=EOF)
{ shs384_process(&sh64,ch); result=FALSE; }
if (e!=NULL)
for (i=0;ilen;i++) shs384_process(&sh64,e->val[i]);
shs384_hash(&sh64,hh);
break;
case SHA512:
shs512_init(&sh64);
if (p!=NULL)
for (i=0;ilen;i++) shs512_process(&sh64,p->val[i]);
if (n!=NULL)
for (i=0;i<4;i++) shs512_process(&sh64,c[i]);
if (x!=NULL)
for (i=0;ilen;i++)
{ shs512_process(&sh64,x->val[i]); result=FALSE; }
if (fp!=NULL)
while ((ch=fgetc(fp))!=EOF)
{ shs512_process(&sh64,ch); result=FALSE; }
if (e!=NULL)
for (i=0;ilen;i++) shs512_process(&sh64,e->val[i]);
shs512_hash(&sh64,hh);
break;
#endif
default:
OCTET_EMPTY(w);
return result;
}
OCTET_EMPTY(w);
OCTET_JOIN_BYTES(hh,hlen,w);
for (i=0;ilen,raw->val,0L);
}
P1363_API void KILL_CSPRNG(csprng *RNG)
{
strong_kill(RNG);
}
/* Mask Generation Function */
P1363_API void MGF1(octet *z,int olen,int hash_type,octet *mask)
{
octet h;
int counter,cthreshold;
int hlen;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return;
OCTET_INIT(&h,hlen);
OCTET_EMPTY(mask);
cthreshold=MR_ROUNDUP(olen,hlen);
for (counter=0;counterlen+hlen>olen) OCTET_JOIN_BYTES(h.val,olen%hlen,mask);
else OCTET_JOIN_OCTET(&h,mask);
}
OCTET_KILL(&h);
}
/*** P1363 recommended Message Encoding Methods ***/
/* message encoding methods for signatures with Appendix */
P1363_API BOOL EMSA1(octet *x,FILE *fp,int bits,int hash_type,octet *w)
{ /* w is a bits-length representative of the *
* octet string message x (if x!=NULL) *
* or of the file fp (if fp!=NULL) *
* w must be initialised for at least 20 bytes */
unsigned char c1,c2;
int i,hlen;
hash(NULL,NULL,x,fp,NULL,hash_type,w);
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
if (bits<8*hlen)
{
for (i=hlen-1;i>bits/8;i--)
{ /* remove bytes off the end */
w->val[i]=0;
w->len--;
}
bits=bits%8;
if (bits!=0)
{
for (i=w->len-1;i>=0;i--)
{
c1=(unsigned char)w->val[i];
c1>>=(8-bits);
if (i>0)
{
c2=(unsigned char)w->val[i-1];
c2<<=bits;
c1|=c2;
}
w->val[i]=(char)c1;
}
}
}
return TRUE;
}
P1363_API BOOL EMSA2(octet *x,FILE *fp,int bits,int hash_type,octet *w)
{ /* w is a bits-length representative of the *
* octet string message x (if x!=NULL) *
* and/or of the file fp (if fp!=NULL) *
* w must be initialised for at least 1+bits/8 *
* bytes */
int lp,hlen;
char id,p1;
octet h;
BOOL zero;
hlen=hash_params(hash_type,NULL);
if (hlen==0 || ((bits+1)%8)!=0) return FALSE;
if (bits<8*hlen+31 || (x!=NULL && fp!=NULL)) return FALSE;
id=sha_id[hash_type];
OCTET_INIT(&h,hlen);
zero=hash(NULL,NULL,x,fp,NULL,hash_type,&h);
p1=0x4b;
if (!zero) p1=0x6b;
lp=((bits+1)/8)-hlen-4;
OCTET_EMPTY(w);
OCTET_JOIN_BYTE(p1,1,w);
OCTET_JOIN_BYTE(0xbb,lp,w);
OCTET_JOIN_BYTE(0xba,1,w);
OCTET_JOIN_OCTET(&h,w);
OCTET_JOIN_BYTE(id,1,w);
OCTET_JOIN_BYTE(0xcc,1,w);
OCTET_KILL(&h);
return TRUE;
}
P1363_API BOOL EMSA3(octet *x,FILE *fp,int bits,int hash_type,octet *w)
{ /* w is a bits-length representative of the *
* octet string message x (if x!=NULL) *
* or of the file fp (if fp!=NULL) *
* w must be initialised big enough to take *
* the result > hlen+hashIDlen+10 bytes */
int olen,hlen,hashIDlen;
unsigned char *idptr;
octet h;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
switch (hash_type)
{
case SHA1:
hashIDlen=SHA160ID[0];
idptr=&SHA160ID[1];
break;
case SHA256:
hashIDlen=SHA256ID[0];
idptr=&SHA256ID[1];
break;
#ifdef mr_unsign64
case SHA384:
hashIDlen=SHA384ID[0];
idptr=&SHA384ID[1];
break;
case SHA512:
hashIDlen=SHA512ID[0];
idptr=&SHA512ID[1];
break;
#endif
default:
break;
}
olen=bits/8;
if (olenhlen+1 || r2len>hlen+1) return FALSE;
}
else
{
if (r1len>hlen || r2len>hlen) return FALSE;
}
if (fp==NULL)
{
if (m2!=NULL) m2len=m2->len;
else m2len=0;
}
else
{
if (m2!=NULL) return FALSE;
m2len=filelength(fp);
}
if (m2len==0) rlen=r1len;
else rlen=r2len;
if (bits<8*rlen) return FALSE;
if (m1len > olen-rlen) return FALSE;
OCTET_INIT(&r,rlen+m1len);
OCTET_COPY(f,&r);
if (!OCTET_PAD(&r,rlen+m1len))
{
OCTET_KILL(&r);
return FALSE;
}
OCTET_CHOP(&r,rlen,m1);
OCTET_INIT(&hh,16+m1len);
OCTET_INIT(&h,hlen+1);
OCTET_JOIN_LONG((long)m1len,8,&hh);
OCTET_JOIN_LONG(m2len,8,&hh);
OCTET_JOIN_OCTET(m1,&hh);
hash(&hh,NULL,m2,fp,v,hash_type,&h);
if (hash_id)
OCTET_JOIN_BYTE(sha_id[hash_type],1,&h);
OCTET_CHOP(&h,rlen,NULL);
result=OCTET_COMPARE(&h,&r);
OCTET_KILL(&r);
OCTET_KILL(&h);
OCTET_KILL(&hh);
return result;
}
P1363_API BOOL EMSR1_ENCODE(BOOL hash_id,int r1len,int r2len,octet *m1,octet *m2,FILE *fp,int bits,int hash_type,octet *v,octet *f)
{ /* m2 can come from an OCTET or from a file.... */
int m1len,rlen,hlen,olen=bits/8;
long m2len;
octet hh,h;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
if (hash_id)
{
if (r1len!=hlen+1 || r2len!=hlen+1) return FALSE;
}
else
{
if (r1len>hlen || r2len>hlen) return FALSE;
}
m1len=m1->len;
if (fp==NULL)
{
if (m2!=NULL) m2len=m2->len;
else m2len=0;
}
else
{
if (m2!=NULL) return FALSE;
m2len=filelength(fp);
}
if (m2len==0) rlen=r1len;
else rlen=r2len;
if (bits<8*rlen) return FALSE;
if (m1len > olen-rlen) return FALSE;
OCTET_INIT(&hh,16+m1len);
OCTET_INIT(&h,hlen+1);
OCTET_JOIN_LONG((long)m1len,8,&hh);
OCTET_JOIN_LONG(m2len,8,&hh);
OCTET_JOIN_OCTET(m1,&hh);
hash(&hh,NULL,m2,fp,v,hash_type,&h);
if (hash_id)
OCTET_JOIN_BYTE(sha_id[hash_type],1,&h);
OCTET_CHOP(&h,rlen,NULL);
OCTET_EMPTY(f);
OCTET_JOIN_OCTET(&h,f);
OCTET_JOIN_OCTET(m1,f);
OCTET_KILL(&h);
OCTET_KILL(&hh);
return TRUE;
}
/* EMSR2 - p is key derivation parameters - NULL by default *
* sym=TRUE - use symmetric encryption
* sym=FALSE - use stream cipher
* assumes KDF2 and AES. */
P1363_API BOOL EMSR2_DECODE(int padlen,BOOL sym,int hash_type,octet *p,octet *c,octet *v,octet *m)
{
int i,len,clen;
octet t,k;
clen=c->len;
if (clen=t.len)
{
OCTET_KILL(&t);
return FALSE;
}
}
OCTET_CHOP(&t,padlen,m);
OCTET_KILL(&t);
return TRUE;
}
P1363_API BOOL EMSR2_ENCODE(int padlen,BOOL sym,int hash_type,octet *p,octet *m,octet *v,octet *c)
{
int mlen;
octet k,t;
if (padlen<1 || padlen>255) return FALSE;
mlen=m->len;
OCTET_INIT(&t,padlen+mlen);
OCTET_JOIN_BYTE(padlen,padlen,&t);
OCTET_JOIN_OCTET(m,&t);
if (sym)
{
OCTET_INIT(&k,16); /* AES Key */
if (!KDF2(v,p,16,hash_type,&k))
{
OCTET_KILL(&t);
OCTET_KILL(&k);
return FALSE;
}
if (!AES_CBC_IV0_ENCRYPT(&k,&t,NULL,c,NULL))
{
OCTET_KILL(&t);
OCTET_KILL(&k);
return FALSE;
}
}
else
{
OCTET_INIT(&k,padlen+mlen);
if (!KDF2(v,p,padlen+mlen,hash_type,&k))
{
OCTET_KILL(&t);
OCTET_KILL(&k);
return FALSE;
}
OCTET_XOR(&k,&t);
OCTET_COPY(&t,c);
}
OCTET_KILL(&t);
OCTET_KILL(&k);
return TRUE;
}
/* PSS Message Encoding */
P1363_API BOOL EMSA4_ENCODE(BOOL hash_id,int hash_type,int slen,csprng *RNG,int bits,octet *m,FILE *fp,octet *f)
{
return EMSR3_ENCODE(hash_id,hash_type,slen,RNG,bits,NULL,m,fp,f);
}
P1363_API BOOL EMSA4_DECODE(BOOL hash_id,int hash_type,int slen,int bits,octet *f,octet *m,FILE *fp)
{
return EMSR3_DECODE(hash_id,hash_type,slen,bits,f,m,fp,NULL);
}
/* PSS-R Message Encoding for signature with recovery */
P1363_API BOOL EMSR3_ENCODE(BOOL hash_id,int hash_type,int slen,csprng *RNG,int bits,octet *m1,octet *m2,FILE *fp,octet *f)
{
int m1len,hlen,u,olen,t,zbytes,dblen;
unsigned char mask;
octet h,salt,md,db;
u=1;
if (hash_id) u=2;
if (m1!=NULL) m1len=m1->len;
else m1len=0;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
olen=MR_ROUNDUP(bits,8);
t=8*olen-bits;
mask=0xFF;
if (t>0) mask>>=t;
if (8*m1len>bits-8*slen-8*hlen-8*u-1) return FALSE;
OCTET_INIT(&h,hlen);
hash(NULL,NULL,m2,fp,NULL,hash_type,&h);
OCTET_INIT(&salt,slen);
OCTET_RAND(RNG,slen,&salt);
OCTET_INIT(&md,8+m1len+hlen+slen);
OCTET_JOIN_LONG(8*m1len,8,&md);
OCTET_JOIN_OCTET(m1,&md);
OCTET_JOIN_OCTET(&h,&md);
OCTET_JOIN_OCTET(&salt,&md);
hash(&md,NULL,NULL,NULL,NULL,hash_type,&h);
OCTET_KILL(&md);
zbytes=olen-m1len-slen-hlen-u;
OCTET_INIT(&db,zbytes+m1len+slen);
OCTET_JOIN_BYTE(0x00,zbytes-1,&db);
OCTET_JOIN_BYTE(0x01,1,&db);
OCTET_JOIN_OCTET(m1,&db);
OCTET_JOIN_OCTET(&salt,&db);
OCTET_KILL(&salt);
dblen=olen-hlen-u;
MGF1(&h,dblen,hash_type,f);
OCTET_XOR(&db,f);
f->val[0]&=mask;
OCTET_JOIN_OCTET(&h,f);
OCTET_KILL(&h);
OCTET_KILL(&db);
if (hash_id)
{
OCTET_JOIN_BYTE(sha_id[hash_type],1,f);
OCTET_JOIN_BYTE(0xcc,1,f);
}
else
OCTET_JOIN_BYTE(0xbc,1,f);
/* remove leading zeros
while (f->val[0]==0) OCTET_SHIFT_LEFT(f,1); */
return TRUE;
}
P1363_API BOOL EMSR3_DECODE(BOOL hash_id,int hash_type,int slen,int bits,octet *f,octet *m2,FILE *fp,octet *m1)
{
int k,t,u,hlen,dblen,m1len,olen;
octet salt,h2,h,db,md,dbmask;
unsigned char mask,ch;
BOOL result;
u=1;
if (hash_id) u=2;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
if (bits<8*slen+8*hlen+8*u+1) return FALSE;
olen=MR_ROUNDUP(bits,8);
t=8*olen-bits;
mask=0xFF;
if (t>0) mask>>=t;
if (!OCTET_PAD(f,olen)) return FALSE;
if (hash_id)
{
if (f->val[olen-1]!=(char)0xcc) return FALSE;
if (f->val[olen-2]!=sha_id[hash_type]) return FALSE;
}
else
if (f->val[olen-1]!=(char)0xbc) return FALSE;
if (f->val[0]&(~mask)) return FALSE;
OCTET_INIT(&h2,hlen);
hash(NULL,NULL,m2,fp,NULL,hash_type,&h2);
OCTET_INIT(&db,olen);
OCTET_INIT(&h,hlen+2);
dblen=olen-hlen-u;
OCTET_COPY(f,&db);
OCTET_CHOP(&db,dblen,&h);
OCTET_CHOP(&h,hlen,NULL);
OCTET_INIT(&dbmask,dblen);
MGF1(&h,dblen,hash_type,&dbmask);
OCTET_XOR(&dbmask,&db);
OCTET_KILL(&dbmask);
db.val[0]&=mask;
OCTET_INIT(&salt,slen);
OCTET_CHOP(&db,dblen-slen,&salt);
k=0;
while (klen;
int hlen,seedlen;
octet dbmask,seed;
hlen=seedlen=hash_params(hash_type,NULL);
if (hlen==0 || mlen>olen-hlen-seedlen-1) return FALSE;
if (m==f) return FALSE; /* must be distinct octets */
hash(p,NULL,NULL,NULL,NULL,hash_type,f);
slen=olen-mlen-hlen-seedlen-1;
OCTET_JOIN_BYTE(0,slen,f);
OCTET_JOIN_BYTE(0x1,1,f);
OCTET_JOIN_OCTET(m,f);
OCTET_INIT(&dbmask,olen-seedlen);
OCTET_INIT(&seed,seedlen);
OCTET_RAND(RNG,seedlen,&seed);
MGF1(&seed,olen-seedlen,hash_type,&dbmask);
OCTET_XOR(f,&dbmask);
MGF1(&dbmask,seedlen,hash_type,f);
OCTET_XOR(&seed,f);
OCTET_JOIN_OCTET(&dbmask,f);
OCTET_KILL(&seed);
OCTET_KILL(&dbmask);
return TRUE;
}
/* OAEP Message Decoding for Decryption */
P1363_API BOOL EME1_DECODE(octet *f,int bits,octet *p,int hash_type,octet *m)
{
BOOL comp;
int i,k,olen=bits/8;
int hlen,seedlen;
octet dbmask,seed,chash;
int x,t;
seedlen=hlen=hash_params(hash_type,NULL);
if (hlen==0 || olenval[0];
for (i=seedlen;ival[i+1];
dbmask.len=olen-seedlen;
MGF1(&dbmask,seedlen,hash_type,&seed);
for (i=0;ival[i+1];
MGF1(&seed,olen-seedlen,hash_type,m);
OCTET_XOR(m,&dbmask);
comp=OCTET_NCOMPARE(&chash,&dbmask,hlen);
OCTET_SHIFT_LEFT(&dbmask,hlen);
OCTET_KILL(&seed);
OCTET_KILL(&chash);
for (k=0;;k++)
{
if (k>=dbmask.len)
{
OCTET_KILL(&dbmask);
return FALSE;
}
if (dbmask.val[k]!=0) break;
}
t=dbmask.val[k];
if (!comp || x!=0 || t!=0x01)
{
OCTET_KILL(&dbmask);
return FALSE;
}
OCTET_SHIFT_LEFT(&dbmask,k+1);
OCTET_COPY(&dbmask,m);
OCTET_KILL(&dbmask);
return TRUE;
}
/*** P1363 Key Derivation Functions ***/
P1363_API void KDF1(octet *z,octet *p,int hash_type,octet *k)
{
hash(z,NULL,p,NULL,NULL,hash_type,k);
}
P1363_API BOOL KDF2(octet *z,octet *p,int olen,int hash_type,octet *k)
{
/* NOTE: the parameter olen is the length of the output k in bytes */
int counter,cthreshold;
int hlen;
octet h;
hlen=hash_params(hash_type,NULL);
if (hlen==0) return FALSE;
cthreshold=MR_ROUNDUP(olen,hlen);
OCTET_EMPTY(k);
OCTET_INIT(&h,hlen);
for (counter=1;counter<=cthreshold;counter++)
{
hash(z,&counter,p,NULL,NULL,hash_type,&h);
if (k->len+hlen>olen) OCTET_JOIN_BYTES(h.val,olen%hlen,k);
else OCTET_JOIN_OCTET(&h,k);
}
OCTET_KILL(&h);
return TRUE;
}
/*** P1363 Message Authentication codes ***/
P1363_API BOOL MAC1(octet *m,FILE *fp,octet *k,int olen,int hash_type,octet *tag)
{
/* Input is either from an octet m, or a file fp. *
* olen is requested output length in bytes. k is the key *
* The output is the calculated tag */
int hlen,b;
octet h,k0;
hlen=hash_params(hash_type,&b);
if (hlen==0 || k->lenhlen) return FALSE;
OCTET_INIT(&k0,b);
OCTET_INIT(&h,hlen);
if (k->len > b) hash(k,NULL,NULL,NULL,NULL,hash_type,&k0);
else OCTET_COPY(k,&k0);
OCTET_JOIN_BYTE(0,b-k0.len,&k0);
OCTET_XOR_BYTE(&k0,0x36);
hash(&k0,NULL,m,fp,NULL,hash_type,&h);
OCTET_XOR_BYTE(&k0,0x6a); /* 0x6a = 0x36 ^ 0x5c */
hash(&k0,NULL,&h,NULL,NULL,hash_type,&h);
OCTET_EMPTY(tag);
OCTET_JOIN_BYTES(h.val,olen,tag);
OCTET_KILL(&h);
OCTET_KILL(&k0);
return TRUE;
}
P1363_API BOOL AES_CBC_IV0_DECRYPT(octet *k,octet *c,FILE *ifp,octet *m,FILE *ofp)
{
aes a;
int i,ipt,opt,ch;
char buff[16];
BOOL fin,bad;
int padlen;
ipt=opt=0;
if (m!=NULL)
{
if (ofp!=NULL) return FALSE;
OCTET_CLEAR(m);
}
if (c!=NULL)
{
if (ifp!=NULL) return FALSE;
if (c->len==0) return FALSE;
else ch=c->val[ipt++];
}
if (!aes_init(&a,MR_CBC,k->len,k->val,NULL)) return FALSE;
if (ifp!=NULL)
{
ch=fgetc(ifp);
if (ch==EOF) return FALSE;
}
fin=FALSE;
forever
{
for (i=0;i<16;i++)
{
if (c!=NULL)
{
buff[i]=ch;
if (ipt>=c->len) {fin=TRUE; break;}
else ch=c->val[ipt++];
}
if (ifp!=NULL)
{
buff[i]=ch;
if ((ch=fgetc(ifp))==EOF) {fin=TRUE; break;}
}
}
aes_decrypt(&a,buff);
if (fin) break;
for (i=0;i<16;i++)
{
if (m!=NULL) if (optmax) m->val[opt++]=buff[i];
if (ofp!=NULL) fputc(buff[i],ofp);
}
}
aes_end(&a);
bad=FALSE;
padlen=buff[15];
if (i!=15 || padlen<1 || padlen>16) bad=TRUE;
if (padlen>=2 && padlen<=16)
for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=TRUE;
if (!bad) for (i=0;i<16-padlen;i++)
{
if (m!=NULL) if (optmax) m->val[opt++]=buff[i];
if (ofp!=NULL) fputc(buff[i],ofp);
}
if (m!=NULL) m->len=opt;
if (bad) return FALSE;
return TRUE;
}
P1363_API BOOL AES_CBC_IV0_ENCRYPT(octet *k,octet *m,FILE *ifp,octet *c,FILE *ofp)
{ /* AES CBC encryption, with Null IV */
/* Input is from either an octet string m, or from a file ifp,
output is to an octet string c, or a file ofp */
aes a;
int i,j,ipt,opt,ch;
char buff[16];
BOOL fin;
int padlen;
if (m!=NULL && ifp!=NULL) return FALSE;
if (c!=NULL)
{
if (ofp!=NULL) return FALSE;
OCTET_CLEAR(c);
}
if (!aes_init(&a,MR_CBC,k->len,k->val,NULL)) return FALSE;
ipt=opt=0;
fin=FALSE;
forever
{
for (i=0;i<16;i++)
{
if (m!=NULL)
{
if (iptlen) buff[i]=m->val[ipt++];
else {fin=TRUE; break;}
}
if (ifp!=NULL)
{
if ((ch=fgetc(ifp))!=EOF) buff[i]=ch;
else {fin=TRUE; break;}
}
}
if (fin) break;
aes_encrypt(&a,buff);
for (i=0;i<16;i++)
{
if (c!=NULL) if (optmax) c->val[opt++]=buff[i];
if (ofp!=NULL) fputc(buff[i],ofp);
}
}
/* last block, filled up to i-th index */
padlen=16-i;
for (j=i;j<16;j++) buff[j]=padlen;
aes_encrypt(&a,buff);
for (i=0;i<16;i++)
{
if (c!=NULL) if (optmax) c->val[opt++]=buff[i];
if (ofp!=NULL) fputc(buff[i],ofp);
}
aes_end(&a);
if (c!=NULL) c->len=opt;
return TRUE;
}
/*** DL primitives - support functions ***/
/* Destroy the DL Domain structure */
P1363_API void DL_DOMAIN_KILL(dl_domain *DOM)
{
OCTET_KILL(&DOM->Q);
OCTET_KILL(&DOM->R);
OCTET_KILL(&DOM->G);
OCTET_KILL(&DOM->K);
OCTET_KILL(&DOM->IK);
#ifndef MR_STATIC
if (DOM->PC.window!=0)
brick_end(&DOM->PC);
#endif
DOM->words=DOM->fsize=0; DOM->H=DOM->rbits=0;
}
/* Initialise the DL domain structure
* It is assumed that the DL domain details are obtained from a file
* or from an array of strings
* multi-precision numbers are read in in Hex
* A suitable file can be generated offline by the MIRACL example program
* dssetup.c
* Set precompute=window size if a precomputed table is to be used to
* speed up the calculation g^x mod p
* Returns recommended number of bytes for use with octet strings */
P1363_API int DL_DOMAIN_INIT(dl_domain *DOM,char *fname,char **params,int precompute)
{ /* get domain details from specified file, OR from an array of strings *
* If input from a file, params=NULL, if input from strings, fname=NULL *
* returns filed size in bytes *
* precompute is 0 for no precomputation, or else window size for Comb method */
FILE *fp;
BOOL tt1,fileinput=TRUE;
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
#endif
miracl *mr_mip;
big q,r,g,k;
int bits,rbits,bytes,rbytes,err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(4)];
memset(mem,0,MR_BIG_RESERVE(4));
#endif
if (fname==NULL && params==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
if (fname==NULL) fileinput=FALSE;
if (fileinput)
{
fp=fopen(fname,"rt");
if (fp==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
fscanf(fp,"%d\n",&bits);
}
else
sscanf(params[0],"%d\n",&bits);
DOM->words=MR_ROUNDUP(bits,MIRACL);
#ifdef MR_GENERIC_AND_STATIC
mr_mip=mirsys(&instance,MR_ROUNDUP(bits,4),16);
#else
mr_mip=mirsys(MR_ROUNDUP(bits,4),16);
#endif
if (mr_mip==NULL)
{
if (fileinput) fclose(fp);
return MR_P1363_OUT_OF_MEMORY;
}
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 4);
if (mem==NULL)
{
if (fileinput) fclose(fp);
res=MR_P1363_OUT_OF_MEMORY;
}
#endif
mr_mip->ERCON=TRUE;
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
r=mirvar_mem(_MIPP_ mem,1);
g=mirvar_mem(_MIPP_ mem,2);
k=mirvar_mem(_MIPP_ mem,3);
bytes=MR_ROUNDUP(bits,8);
if (fileinput)
{
innum(_MIPP_ q,fp);
innum(_MIPP_ r,fp);
innum(_MIPP_ g,fp);
fclose(fp);
}
else
{
instr(_MIPP_ q,params[1]);
instr(_MIPP_ r,params[2]);
instr(_MIPP_ g,params[3]);
}
rbits=logb2(_MIPP_ r); /* r is usually much smaller than q */
rbytes=MR_ROUNDUP(rbits,8);
OCTET_INIT(&DOM->Q,bytes);
OCTET_INIT(&DOM->R,rbytes);
OCTET_INIT(&DOM->G,bytes);
OCTET_INIT(&DOM->K,bytes);
OCTET_INIT(&DOM->IK,rbytes);
DOM->H=(1+rbits)/2;
DOM->fsize=bytes;
DOM->rbits=rbits;
decr(_MIPP_ q,1,k);
divide(_MIPP_ k,r,k); /* k=(q-1)/r */
convert_big_octet(_MIPP_ q,&DOM->Q);
convert_big_octet(_MIPP_ r,&DOM->R);
convert_big_octet(_MIPP_ g,&DOM->G);
convert_big_octet(_MIPP_ k,&DOM->K);
xgcd(_MIPP_ k,r,k,k,k);
convert_big_octet(_MIPP_ k,&DOM->IK);
DOM->PC.window=0;
#ifndef MR_STATIC
if (precompute)
brick_init(_MIPP_ &DOM->PC,g,q,precompute,logb2(_MIPP_ r));
#endif
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,4);
#else
memset(mem,0,MR_BIG_RESERVE(4));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
if (res<0) return res;
else return bytes;
}
/* validate DL domain details - good idea if you got them from
* some-one else! */
P1363_API int DL_DOMAIN_VALIDATE(BOOL (*idle)(void),dl_domain *DOM)
{ /* do domain checks - IEEE P1363 A16.2 */
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,t;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(4)];
memset(mem,0,MR_BIG_RESERVE(4));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
mr_mip->NTRY=50;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 4);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
r=mirvar_mem(_MIPP_ mem,1);
g=mirvar_mem(_MIPP_ mem,2);
t=mirvar_mem(_MIPP_ mem,3);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
if (size(g)<2 || size(q)<=2 || size(r)<=2) res=MR_P1363_DOMAIN_ERROR;
if (mr_compare(g,q)>=0) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
gprime(_MIPP_ 10000);
if (!isprime(_MIPP_ q)) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
if (!isprime(_MIPP_ r)) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{ /* is g of order r? */
powmod(_MIPP_ g,r,q,t);
if (size(t)!=1) res=MR_P1363_DOMAIN_ERROR;
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,4);
#else
memset(mem,0,MR_BIG_RESERVE(4));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* Calculate a public/private DL key pair. W=g^S mod p
* where S is the private key and W the public key
* If RNG is NULL then the private key is provided externally in S
* otherwise it is generated randomly internally
*/
P1363_API int DL_KEY_PAIR_GENERATE(BOOL (*idle)(void),dl_domain *DOM,csprng *RNG, octet *S,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,s,w;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(5)];
memset(mem,0,MR_BIG_RESERVE(5));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 5);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
r=mirvar_mem(_MIPP_ mem,1);
g=mirvar_mem(_MIPP_ mem,2);
s=mirvar_mem(_MIPP_ mem,3);
w=mirvar_mem(_MIPP_ mem,4);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
if (RNG!=NULL)
{
strong_bigrand(_MIPP_ RNG,r,s);
}
else
{
OS2FEP(_MIPP_ S,s);
divide(_MIPP_ s,r,r);
}
if (DOM->PC.window==0)
powmod(_MIPP_ g,s,q,w);
else
pow_brick(_MIPP_ &DOM->PC,s,w);
if (RNG!=NULL) convert_big_octet(_MIPP_ s,S);
FE2OSP(_MIPP_ w,DOM->fsize,W);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,5);
#else
memset(mem,0,MR_BIG_RESERVE(5));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* validate a DL public key. Set full=TRUE for fuller,
* but more time-consuming test */
P1363_API int DL_PUBLIC_KEY_VALIDATE(BOOL (*idle)(void),dl_domain *DOM,BOOL full,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,w,t;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(4)];
memset(mem,0,MR_BIG_RESERVE(4));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 4);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
r=mirvar_mem(_MIPP_ mem,1);
w=mirvar_mem(_MIPP_ mem,2);
t=mirvar_mem(_MIPP_ mem,3);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ W,w);
if (size(w)<2 || mr_compare(w,q)>=0) res=MR_P1363_INVALID_PUBLIC_KEY;
}
if (res==0 && full)
{
powmod(_MIPP_ w,r,q,t);
if (size(t)!=1) res=MR_P1363_INVALID_PUBLIC_KEY;
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,4);
#else
memset(mem,0,MR_BIG_RESERVE(4));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** P1363 DL primitives ***/
/* See P1363 documentation for specification */
P1363_API int DLSVDP_DH(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *WD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,s,wd,z;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(4)];
memset(mem,0,MR_BIG_RESERVE(4));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 4);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
s=mirvar_mem(_MIPP_ mem,1);
wd=mirvar_mem(_MIPP_ mem,2);
z=mirvar_mem(_MIPP_ mem,3);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ WD,wd);
powmod(_MIPP_ wd,s,q,z);
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,4);
#else
memset(mem,0,MR_BIG_RESERVE(4));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSVDP_DHC(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *WD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,k,ik,s,wd,t,z;
int sz;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem,0);
r=mirvar_mem(_MIPP_ mem,1);
k=mirvar_mem(_MIPP_ mem,2);
ik=mirvar_mem(_MIPP_ mem,3);
s=mirvar_mem(_MIPP_ mem,4);
wd=mirvar_mem(_MIPP_ mem,5);
z=mirvar_mem(_MIPP_ mem,6);
t=mirvar_mem(_MIPP_ mem,7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ WD,wd);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ ik,s,ik,r,r,t); /* t=s/k mod r */
}
else copy(s,t);
multiply(_MIPP_ t,k,t); /* kt */
powmod(_MIPP_ wd,t,q,z);
sz=size(z);
if (sz==0 || sz==1) res=MR_P1363_INVALID_PUBLIC_KEY;
else FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSVDP_MQV(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
int h;
int err,res=0;
big q,r,s,u,v,wd,vd,e,t,td,z;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(11)];
memset(mem,0,MR_BIG_RESERVE(11));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
s=mirvar_mem(_MIPP_ mem, 2);
u=mirvar_mem(_MIPP_ mem, 3);
v=mirvar_mem(_MIPP_ mem, 4);
wd=mirvar_mem(_MIPP_ mem, 5);
vd=mirvar_mem(_MIPP_ mem, 6);
e=mirvar_mem(_MIPP_ mem, 7);
t=mirvar_mem(_MIPP_ mem, 8);
td=mirvar_mem(_MIPP_ mem, 9);
z=mirvar_mem(_MIPP_ mem, 10);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ V,v);
OS2FEP(_MIPP_ WD,wd);
OS2FEP(_MIPP_ VD,vd);
h=DOM->H;
expb2(_MIPP_ h,z);
copy(v,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy(vd,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
powmod2(_MIPP_ vd,e,wd,t,q,z);
if (size(z)==1) res= MR_P1363_ERROR;
else FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
#else
memset(mem,0,MR_BIG_RESERVE(11));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSVDP_MQVC(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
int sz,h;
big q,r,s,u,v,wd,vd,e,t,td,z,k,ik;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(13)];
memset(mem,0,MR_BIG_RESERVE(13));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 13);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
ik=mirvar_mem(_MIPP_ mem, 2);
k=mirvar_mem(_MIPP_ mem, 3);
s=mirvar_mem(_MIPP_ mem, 4);
u=mirvar_mem(_MIPP_ mem, 5);
v=mirvar_mem(_MIPP_ mem, 6);
wd=mirvar_mem(_MIPP_ mem, 7);
vd=mirvar_mem(_MIPP_ mem, 8);
e=mirvar_mem(_MIPP_ mem, 9);
t=mirvar_mem(_MIPP_ mem, 10);
td=mirvar_mem(_MIPP_ mem, 11);
z=mirvar_mem(_MIPP_ mem, 12);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ V,v);
OS2FEP(_MIPP_ WD,wd);
OS2FEP(_MIPP_ VD,vd);
h=DOM->H;
expb2(_MIPP_ h,z);
copy(v,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy(vd,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ e,ik,e,r,r,e);
}
mad(_MIPP_ e,k,e,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
powmod2(_MIPP_ vd,e,wd,t,q,z);
sz=size(z);
if (sz==0 || sz==1) res=MR_P1363_INVALID_PUBLIC_KEY;
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,13);
#else
memset(mem,0,MR_BIG_RESERVE(13));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLVP_NR(BOOL (*idle)(void),dl_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,w,f,c,d;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(7)];
memset(mem,0,MR_BIG_RESERVE(7));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
w=mirvar_mem(_MIPP_ mem, 3);
f=mirvar_mem(_MIPP_ mem, 4);
c=mirvar_mem(_MIPP_ mem, 5);
d=mirvar_mem(_MIPP_ mem, 6);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ W,w);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<0 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
powmod2(_MIPP_ g,d,w,c,q,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
#else
memset(mem,0,MR_BIG_RESERVE(7));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSP_NR(BOOL (*idle)(void),dl_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,s,f,c,d,u,v;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(9)];
memset(mem,0,MR_BIG_RESERVE(9));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
f=mirvar_mem(_MIPP_ mem, 4);
c=mirvar_mem(_MIPP_ mem, 5);
d=mirvar_mem(_MIPP_ mem, 6);
u=mirvar_mem(_MIPP_ mem, 7);
v=mirvar_mem(_MIPP_ mem, 8);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
powmod(_MIPP_ g,u,q,v);
else
pow_brick(_MIPP_ &DOM->PC,u,v);
add(_MIPP_ v,f,c);
divide(_MIPP_ c,r,r);
} while (size(c)==0);
}
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
#else
memset(mem,0,MR_BIG_RESERVE(9));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLVP_DSA(BOOL (*idle)(void),dl_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,w,f,c,d,h2;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
w=mirvar_mem(_MIPP_ mem, 3);
f=mirvar_mem(_MIPP_ mem, 4);
c=mirvar_mem(_MIPP_ mem, 5);
d=mirvar_mem(_MIPP_ mem, 6);
h2=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ W,w);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
OS2FEP(_MIPP_ F,f);
if (size(c)<1 || size(d)<1 || mr_compare(c,r)>=0 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
xgcd(_MIPP_ d,r,d,d,d);
mad(_MIPP_ f,d,f,r,r,f);
mad(_MIPP_ c,d,c,r,r,h2);
powmod2(_MIPP_ g,f,w,h2,q,d);
divide(_MIPP_ d,r,r);
if (mr_compare(d,c)!=0) res=MR_P1363_INVALID;
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSP_DSA(BOOL (*idle)(void),dl_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,s,f,c,d,u,v;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(9)];
memset(mem,0,MR_BIG_RESERVE(9));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
f=mirvar_mem(_MIPP_ mem, 4);
c=mirvar_mem(_MIPP_ mem, 5);
d=mirvar_mem(_MIPP_ mem, 6);
u=mirvar_mem(_MIPP_ mem, 7);
v=mirvar_mem(_MIPP_ mem, 8);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
powmod(_MIPP_ g,u,q,v);
else
pow_brick(_MIPP_ &DOM->PC,u,v);
copy(v,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) continue;
xgcd(_MIPP_ u,r,u,u,u);
mad(_MIPP_ s,c,f,r,r,d);
mad(_MIPP_ u,d,u,r,r,d);
} while (size(d)==0);
if (res==0)
{
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
#else
memset(mem,0,MR_BIG_RESERVE(9));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLPSP_NR2PV(BOOL (*idle)(void),dl_domain *DOM,csprng *RNG,octet *U,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,u,v;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(5)];
memset(mem,0,MR_BIG_RESERVE(5));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 5);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
u=mirvar_mem(_MIPP_ mem, 3);
v=mirvar_mem(_MIPP_ mem, 4);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
powmod(_MIPP_ g,u,q,v);
else
pow_brick(_MIPP_ &DOM->PC,u,v);
convert_big_octet(_MIPP_ u,U);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,5);
#else
memset(mem,0,MR_BIG_RESERVE(5));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSP_NR2(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *U,octet *V,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,u,v,c,d,s,f;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
s=mirvar_mem(_MIPP_ mem, 2);
f=mirvar_mem(_MIPP_ mem, 3);
u=mirvar_mem(_MIPP_ mem, 4);
v=mirvar_mem(_MIPP_ mem, 5);
c=mirvar_mem(_MIPP_ mem, 6);
d=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ V,v);
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
if (size(u)<1 || mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
if (size(v)<1 || mr_compare(v,q)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
add(_MIPP_ v,f,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) res=MR_P1363_ERROR;
}
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLVP_NR2(BOOL (*idle)(void),dl_domain *DOM,octet *W,octet *C,octet *D,octet *F,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,c,d,w,f,v;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
w=mirvar_mem(_MIPP_ mem, 3);
c=mirvar_mem(_MIPP_ mem, 4);
d=mirvar_mem(_MIPP_ mem, 5);
f=mirvar_mem(_MIPP_ mem, 6);
v=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ W,w);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
powmod2(_MIPP_ g,d,w,c,q,v);
copy(v,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLSP_PV(BOOL (*idle)(void),dl_domain *DOM,octet *S,octet *U,octet *H,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,h,u,d,s;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(6)];
memset(mem,0,MR_BIG_RESERVE(6));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 6);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
s=mirvar_mem(_MIPP_ mem, 2);
u=mirvar_mem(_MIPP_ mem, 3);
h=mirvar_mem(_MIPP_ mem, 4);
d=mirvar_mem(_MIPP_ mem, 5);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ H,h);
if (mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
mad(_MIPP_ s,h,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,6);
#else
memset(mem,0,MR_BIG_RESERVE(6));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int DLVP_PV(BOOL (*idle)(void),dl_domain *DOM,octet *W,octet *H,octet *D,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,g,d,w,h,v;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(7)];
memset(mem,0,MR_BIG_RESERVE(7));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=FALSE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
g=mirvar_mem(_MIPP_ mem, 2);
w=mirvar_mem(_MIPP_ mem, 3);
h=mirvar_mem(_MIPP_ mem, 4);
d=mirvar_mem(_MIPP_ mem, 5);
v=mirvar_mem(_MIPP_ mem, 6);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->G,g);
OS2FEP(_MIPP_ W,w);
OS2FEP(_MIPP_ D,d);
OS2FEP(_MIPP_ H,h);
if (mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
powmod2(_MIPP_ g,d,w,h,q,v);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
#else
memset(mem,0,MR_BIG_RESERVE(7));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** EC GF(p) primitives - support functions ***/
/* destroy the EC GF(p) domain structure */
P1363_API void ECP_DOMAIN_KILL(ecp_domain *DOM)
{
OCTET_KILL(&DOM->Q);
OCTET_KILL(&DOM->A);
OCTET_KILL(&DOM->B);
OCTET_KILL(&DOM->R);
OCTET_KILL(&DOM->Gx);
OCTET_KILL(&DOM->Gy);
OCTET_KILL(&DOM->K);
OCTET_KILL(&DOM->IK);
#ifndef MR_STATIC
if (DOM->PC.window!=0)
ebrick_end(&DOM->PC);
#endif
DOM->words=DOM->fsize=0; DOM->H=DOM->rbits=0;
}
/* Initialise the EC GF(p) domain structure
* It is assumed that the EC domain details are obtained from a file
* or from an array of strings
* multiprecision numbers are read in in Hex
* A suitable file can be generated offline by the MIRACL example program
* schoof.exe
* Set precompute=window size if a precomputed table is to be used to
* speed up the calculation x.G mod EC(p)
* Returns field size in bytes */
P1363_API int ECP_DOMAIN_INIT(ecp_domain *DOM,char *fname,char **params,int precompute)
{ /* get domain details from specified file */
/* If input from a file, params=NULL, if input from strings, fname=NULL */
/* return max. size in bytes of octet strings */
/* precompute is 0 for no precomputation, or else window size for Comb method */
FILE *fp;
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
#endif
miracl *mr_mip;
BOOL fileinput=TRUE;
big q,r,gx,gy,a,b,k;
int bits,rbits,bytes,err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(7)];
memset(mem,0,MR_BIG_RESERVE(7));
#endif
if (fname==NULL && params==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
if (fname==NULL) fileinput=FALSE;
if (fileinput)
{
fp=fopen(fname,"rt");
if (fp==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
fscanf(fp,"%d\n",&bits);
}
else
sscanf(params[0],"%d\n",&bits);
DOM->words=MR_ROUNDUP(bits,MIRACL);
#ifdef MR_GENERIC_AND_STATIC
mr_mip=mirsys(&instance,MR_ROUNDUP(bits,4),16);
#else
mr_mip=mirsys(MR_ROUNDUP(bits,4),16);
#endif
if (mr_mip==NULL)
{
if (fileinput) fclose(fp);
return MR_P1363_OUT_OF_MEMORY;
}
mr_mip->ERCON=TRUE;
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
k=mirvar_mem(_MIPP_ mem, 6);
bytes=MR_ROUNDUP(bits,8);
if (fileinput)
{
innum(_MIPP_ q,fp);
innum(_MIPP_ a,fp);
innum(_MIPP_ b,fp);
innum(_MIPP_ r,fp);
innum(_MIPP_ gx,fp);
innum(_MIPP_ gy,fp);
fclose(fp);
}
else
{
instr(_MIPP_ q,params[1]);
instr(_MIPP_ a,params[2]);
instr(_MIPP_ b,params[3]);
instr(_MIPP_ r,params[4]);
instr(_MIPP_ gx,params[5]);
instr(_MIPP_ gy,params[6]);
}
OCTET_INIT(&DOM->Q,bytes);
OCTET_INIT(&DOM->A,bytes);
OCTET_INIT(&DOM->B,bytes);
OCTET_INIT(&DOM->R,bytes);
OCTET_INIT(&DOM->Gx,bytes);
OCTET_INIT(&DOM->Gy,bytes);
OCTET_INIT(&DOM->K,bytes);
OCTET_INIT(&DOM->IK,bytes);
rbits=logb2(_MIPP_ r);
DOM->H=(1+rbits)/2;
DOM->fsize=bytes;
DOM->rbits=rbits;
nroot(_MIPP_ q,2,k);
premult(_MIPP_ k,2,k);
add(_MIPP_ k,q,k);
incr(_MIPP_ k,3,k);
divide(_MIPP_ k,r,k); /* get co-factor k = (q+2q^0.5+3)/r */
if (size(a)<0) add(_MIPP_ q,a,a);
if (size(b)<0) add(_MIPP_ q,b,b);
convert_big_octet(_MIPP_ q,&DOM->Q);
convert_big_octet(_MIPP_ a,&DOM->A);
convert_big_octet(_MIPP_ b,&DOM->B);
convert_big_octet(_MIPP_ r,&DOM->R);
convert_big_octet(_MIPP_ gx,&DOM->Gx);
convert_big_octet(_MIPP_ gy,&DOM->Gy);
convert_big_octet(_MIPP_ k,&DOM->K);
xgcd(_MIPP_ k,r,k,k,k);
convert_big_octet(_MIPP_ k,&DOM->IK);
DOM->PC.window=0;
#ifndef MR_STATIC
if (precompute) ebrick_init(_MIPP_ &DOM->PC,gx,gy,a,b,q,precompute,logb2(_MIPP_ r));
#endif
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
#else
memset(mem,0,MR_BIG_RESERVE(7));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
if (res<0) return res;
else return bytes;
}
/* validate EC GF(p) domain details - good idea if you got them from
* some-one else! */
P1363_API int ECP_DOMAIN_VALIDATE(BOOL (*idle)(void),ecp_domain *DOM)
{ /* do domain checks - A16.8 */
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,gx,gy,t,w;
epoint *G;
int i,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(8)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
mr_mip->NTRY=50;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
t=mirvar_mem(_MIPP_ mem, 6);
w=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
nroot(_MIPP_ q,2,t);
premult(_MIPP_ t,4,t);
if (mr_compare(r,t)<=0) res=MR_P1363_DOMAIN_ERROR;
if (mr_compare(b,q)>=0) res=MR_P1363_DOMAIN_ERROR;
if (mr_compare(r,q)==0) res=MR_P1363_DOMAIN_ERROR;
if (size(r)<3 || size(q)<3) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
gprime(_MIPP_ 10000);
if (!isprime(_MIPP_ r)) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
if (!isprime(_MIPP_ q)) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{ /* check 4a^3+27b^2 !=0 mod q */
mad(_MIPP_ b,b,b,q,q,t);
premult(_MIPP_ t,27,t);
mad(_MIPP_ a,a,a,q,q,w);
mad(_MIPP_ w,a,a,q,q,w);
premult(_MIPP_ w,4,w);
add(_MIPP_ t,w,t);
divide(_MIPP_ t,q,q);
if (size(t)<0) add(_MIPP_ t,q,t);
if (size(t)==0) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_AFFINE);
G=epoint_init_mem(_MIPP_ mem1,0);
if (!epoint_set(_MIPP_ gx,gy,0,G)) res=MR_P1363_DOMAIN_ERROR;
if (G->marker==MR_EPOINT_INFINITY) res=MR_P1363_DOMAIN_ERROR;
else
{
ecurve_mult(_MIPP_ r,G,G);
if (G->marker!=MR_EPOINT_INFINITY) res=MR_P1363_DOMAIN_ERROR;
}
}
if (res==0)
{ /* MOV conditon */
convert(_MIPP_ 1,t);
for (i=0;i<50;i++)
{
mad(_MIPP_ t,q,q,r,r,t);
if (size(t)==1)
{
res=MR_P1363_DOMAIN_ERROR;
break;
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* Calculate a public/private EC GF(p) key pair. W=S.g mod EC(p),
* where S is the secret key and W is the public key
* Indicate if "point compression" is required for public key
* If RNG is NULL then the private key is provided externally in S
* otherwise it is generated randomly internally */
P1363_API int ECP_KEY_PAIR_GENERATE(BOOL (*idle)(void),ecp_domain *DOM,csprng *RNG,octet* S,BOOL compress,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,gx,gy,s,wx,wy;
epoint *G,*WP;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#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) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
epoint_set(_MIPP_ gx,gy,0,G);
if (RNG!=NULL)
strong_bigrand(_MIPP_ RNG,r,s);
else
{
OS2FEP(_MIPP_ S,s);
divide(_MIPP_ s,r,r);
}
if (DOM->PC.window==0)
{
ecurve_mult(_MIPP_ s,G,WP);
bit=epoint_get(_MIPP_ WP,wx,wy);
}
else
bit=mul_brick(_MIPP_ &DOM->PC,s,wx,wy);
if (RNG!=NULL) convert_big_octet(_MIPP_ s,S);
EC2OSP(_MIPP_ wx,wy,bit,compress,DOM->fsize,W);
}
#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 MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* validate an EC GF(p) public key. Set full=TRUE for fuller,
* but more time-consuming test */
P1363_API int ECP_PUBLIC_KEY_VALIDATE(BOOL (*idle)(void),ecp_domain *DOM,BOOL full,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,wx,wy;
epoint *WP;
BOOL valid,compressed;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(6)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(6));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 6);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
r=mirvar_mem(_MIPP_ mem, 3);
wx=mirvar_mem(_MIPP_ mem, 4);
wy=mirvar_mem(_MIPP_ mem, 5);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (W->lenfsize+1 || W->len>2*DOM->fsize+1) res=MR_P1363_INVALID_PUBLIC_KEY;
if (mr_compare(wx,q)>=0 || mr_compare (wy,q)>=0) res=MR_P1363_INVALID_PUBLIC_KEY;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
WP=epoint_init_mem(_MIPP_ mem1,0);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,WP);
else valid=epoint_set(_MIPP_ wx,wx,bit,WP);
if (!valid || WP->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
if (res==0 && full)
{
ecurve_mult(_MIPP_ r,WP,WP);
if (WP->marker!=MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,6);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(6));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** P1363 EC GF(p) primitives ***/
/* See P1363 documentation for specification */
/* Note the support for point compression */
P1363_API int ECPSVDP_DH(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *WD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,s,wx,wy,z;
BOOL valid,compressed;
epoint *W;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(7)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
wx=mirvar_mem(_MIPP_ mem, 4);
wy=mirvar_mem(_MIPP_ mem, 5);
z=mirvar_mem(_MIPP_ mem, 6);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ S,s);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
W=epoint_init_mem(_MIPP_ mem1,0);
compressed=OS2ECP(_MIPP_ WD,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,W);
else valid=epoint_set(_MIPP_ wx,wx,bit,W);
if (!valid) res=MR_P1363_ERROR;
ecurve_mult(_MIPP_ s,W,W);
if (W->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint_get(_MIPP_ W,z,z);
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSVDP_DHC(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *WD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,s,wx,wy,z,k,ik,t;
BOOL compressed,valid;
epoint *W;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
s=mirvar_mem(_MIPP_ mem, 4);
wx=mirvar_mem(_MIPP_ mem, 5);
wy=mirvar_mem(_MIPP_ mem, 6);
k=mirvar_mem(_MIPP_ mem, 7);
ik=mirvar_mem(_MIPP_ mem, 8);
z=mirvar_mem(_MIPP_ mem, 9);
t=mirvar_mem(_MIPP_ mem, 10);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ S,s);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ ik,s,ik,r,r,t); /* t=s/k mod r */
}
else copy(s,t);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
W=epoint_init_mem(_MIPP_ mem1,0);
compressed=OS2ECP(_MIPP_ WD,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,W);
else valid=epoint_set(_MIPP_ wx,wx,bit,W);
if (!valid) res=MR_P1363_ERROR;
else
{
multiply(_MIPP_ t,k,t);
ecurve_mult(_MIPP_ t,W,W);
if (W->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint_get(_MIPP_ W,z,z);
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSVDP_MQV(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,s,u,vx,wdx,wdy,vdx,vdy,z,e,t,td;
epoint *P,*WDP,*VDP;
BOOL compressed,valid;
int bit,h,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(15)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(15));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 15);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
s=mirvar_mem(_MIPP_ mem, 4);
u=mirvar_mem(_MIPP_ mem, 5);
vx=mirvar_mem(_MIPP_ mem, 6);
wdx=mirvar_mem(_MIPP_ mem, 7);
wdy=mirvar_mem(_MIPP_ mem, 8);
vdx=mirvar_mem(_MIPP_ mem, 9);
vdy=mirvar_mem(_MIPP_ mem, 10);
z=mirvar_mem(_MIPP_ mem, 11);
e=mirvar_mem(_MIPP_ mem, 12);
t=mirvar_mem(_MIPP_ mem, 13);
td=mirvar_mem(_MIPP_ mem, 14);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
P=epoint_init_mem(_MIPP_ mem1,0);
OS2ECP(_MIPP_ V,vx,NULL,DOM->fsize,&bit);
WDP=epoint_init_mem(_MIPP_ mem1,1);
compressed=OS2ECP(_MIPP_ WD,wdx,wdy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wdx,wdy,0,WDP);
else valid=epoint_set(_MIPP_ wdx,wdx,bit,WDP);
if (!valid) res=MR_P1363_ERROR;
else
{
VDP=epoint_init_mem(_MIPP_ mem1,2);
compressed=OS2ECP(_MIPP_ VD,vdx,vdy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ vdx,vdy,0,VDP);
else valid=epoint_set(_MIPP_ vdx,vdx,bit,VDP);
if (!valid) res=MR_P1363_ERROR;
else
{
h=DOM->H;
expb2(_MIPP_ h,z);
copy(vx,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy (vdx,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
ecurve_mult2(_MIPP_ e,VDP,t,WDP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint_get(_MIPP_ P,z,z);
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,15);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(15));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSVDP_MQVC(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,s,u,vx,wdx,wdy,vdx,vdy,z,e,t,td,k,ik;
epoint *P,*WDP,*VDP;
BOOL compressed,valid;
int bit,h,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(17)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(17));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 17);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
ik=mirvar_mem(_MIPP_ mem, 4);
k=mirvar_mem(_MIPP_ mem, 5);
s=mirvar_mem(_MIPP_ mem, 6);
u=mirvar_mem(_MIPP_ mem, 7);
vx=mirvar_mem(_MIPP_ mem, 8);
wdx=mirvar_mem(_MIPP_ mem, 9);
wdy=mirvar_mem(_MIPP_ mem, 10);
vdx=mirvar_mem(_MIPP_ mem, 11);
vdy=mirvar_mem(_MIPP_ mem, 12);
z=mirvar_mem(_MIPP_ mem, 13);
e=mirvar_mem(_MIPP_ mem, 14);
t=mirvar_mem(_MIPP_ mem, 15);
td=mirvar_mem(_MIPP_ mem, 16);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
P=epoint_init_mem(_MIPP_ mem1,0);
OS2ECP(_MIPP_ V,vx,NULL,DOM->fsize,&bit);
WDP=epoint_init_mem(_MIPP_ mem1,1);
compressed=OS2ECP(_MIPP_ WD,wdx,wdy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wdx,wdy,0,WDP);
else valid=epoint_set(_MIPP_ wdx,wdx,bit,WDP);
if (!valid) res=MR_P1363_ERROR;
else
{
VDP=epoint_init_mem(_MIPP_ mem1,2);
compressed=OS2ECP(_MIPP_ VD,vdx,vdy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ vdx,vdy,0,VDP);
else valid=epoint_set(_MIPP_ vdx,vdx,bit,VDP);
if (!valid) res=MR_P1363_ERROR;
else
{
h=DOM->H;
expb2(_MIPP_ h,z);
copy(vx,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy (vdx,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ e,ik,e,r,r,e);
}
mad(_MIPP_ e,k,e,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
ecurve_mult2(_MIPP_ e,VDP,t,WDP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
else
{
epoint_get(_MIPP_ P,z,z);
FE2OSP(_MIPP_ z,DOM->fsize,Z);
}
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,17);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(17));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSP_NR(BOOL (*idle)(void),ecp_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,gx,gy,r,s,f,c,d,u,vx;
epoint *G,*V;
int err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(12)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 12);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
r=mirvar_mem(_MIPP_ mem, 5);
s=mirvar_mem(_MIPP_ mem, 6);
f=mirvar_mem(_MIPP_ mem, 7);
c=mirvar_mem(_MIPP_ mem, 8);
d=mirvar_mem(_MIPP_ mem, 9);
u=mirvar_mem(_MIPP_ mem, 10);
vx=mirvar_mem(_MIPP_ mem,11);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
V=epoint_init_mem(_MIPP_ mem1,1);
epoint_set(_MIPP_ gx,gy,0,G);
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve_mult(_MIPP_ u,G,V);
epoint_get(_MIPP_ V,vx,vx);
}
else
mul_brick(_MIPP_ &DOM->PC,u,vx,vx);
divide(_MIPP_ vx,r,r);
add(_MIPP_ vx,f,c);
divide(_MIPP_ c,r,r);
} while (size(c)==0);
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,12);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPVP_NR(BOOL (*idle)(void),ecp_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,a,b,gx,gy,wx,wy,f,c,d;
int bit,err,res=0;
epoint *G,*WP,*P;
BOOL compressed,valid;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
r=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
f=mirvar_mem(_MIPP_ mem, 8);
c=mirvar_mem(_MIPP_ mem, 9);
d=mirvar_mem(_MIPP_ mem, 10);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<0 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,WP);
else valid=epoint_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve_mult2(_MIPP_ d,G,c,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint_get(_MIPP_ P,f,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPPSP_NR2PV(BOOL (*idle)(void),ecp_domain *DOM,csprng *RNG,octet *U,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,gx,gy,r,u,vx;
epoint *G,*VP;
int err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(8)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
r=mirvar_mem(_MIPP_ mem, 5);
u=mirvar_mem(_MIPP_ mem, 6);
vx=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
VP=epoint_init_mem(_MIPP_ mem1,1);
epoint_set(_MIPP_ gx,gy,0,G);
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve_mult(_MIPP_ u,G,VP);
epoint_get(_MIPP_ VP,vx,vx);
}
else
mul_brick(_MIPP_ &DOM->PC,u,vx,vx);
convert_big_octet(_MIPP_ u,U);
FE2OSP(_MIPP_ vx,DOM->fsize,V);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSP_NR2(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *U,octet *V,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,u,v,s,c,d,f;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
u=mirvar_mem(_MIPP_ mem, 2);
v=mirvar_mem(_MIPP_ mem, 3);
s=mirvar_mem(_MIPP_ mem, 4);
c=mirvar_mem(_MIPP_ mem, 5);
d=mirvar_mem(_MIPP_ mem, 6);
f=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ V,v);
if (size(u)<1 || mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
if (size(v)<1 || mr_compare(v,q)>=0) res=MR_P1363_BAD_ASSUMPTION;
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
add(_MIPP_ v,f,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) res=MR_P1363_ERROR;
}
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPVP_NR2(BOOL (*idle)(void),ecp_domain *DOM,octet *W,octet *C,octet *D,octet *F,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,a,b,gx,gy,v,wx,wy,c,d,f;
epoint *G,*WP,*P;
BOOL compressed,valid;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(12)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 12);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
a=mirvar_mem(_MIPP_ mem, 2);
b=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);
c=mirvar_mem(_MIPP_ mem, 9);
d=mirvar_mem(_MIPP_ mem, 10);
f=mirvar_mem(_MIPP_ mem, 11);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,WP);
else valid=epoint_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve_mult2(_MIPP_ d,G,c,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint_get(_MIPP_ P,v,v);
copy(v,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,12);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSP_PV(BOOL (*idle)(void),ecp_domain *DOM,octet *S,octet *U,octet *H,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,u,s,d,h;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(6)];
memset(mem,0,MR_BIG_RESERVE(6));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 6);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
u=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
d=mirvar_mem(_MIPP_ mem, 4);
h=mirvar_mem(_MIPP_ mem, 5);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ H,h);
if (size(u)<1 || mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
mad(_MIPP_ s,h,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,6);
#else
memset(mem,0,MR_BIG_RESERVE(6));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPVP_PV(BOOL (*idle)(void),ecp_domain *DOM,octet *W,octet *H,octet *D,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,a,b,gx,gy,v,wx,wy,d,h;
epoint *G,*WP,*P;
BOOL compressed,valid;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
a=mirvar_mem(_MIPP_ mem, 2);
b=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);
d=mirvar_mem(_MIPP_ mem, 9);
h=mirvar_mem(_MIPP_ mem, 10);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ H,h);
OS2FEP(_MIPP_ D,d);
if (mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,WP);
else valid=epoint_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve_mult2(_MIPP_ d,G,h,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint_get(_MIPP_ P,v,v);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPSP_DSA(BOOL (*idle)(void),ecp_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,gx,gy,r,s,f,c,d,u,vx;
epoint *G,*V;
int err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(12)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 12);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
r=mirvar_mem(_MIPP_ mem, 5);
s=mirvar_mem(_MIPP_ mem, 6);
f=mirvar_mem(_MIPP_ mem, 7);
c=mirvar_mem(_MIPP_ mem, 8);
d=mirvar_mem(_MIPP_ mem, 9);
u=mirvar_mem(_MIPP_ mem, 10);
vx=mirvar_mem(_MIPP_ mem,11);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
V=epoint_init_mem(_MIPP_ mem1,1);
epoint_set(_MIPP_ gx,gy,0,G);
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve_mult(_MIPP_ u,G,V);
epoint_get(_MIPP_ V,vx,vx);
}
else
mul_brick(_MIPP_ &DOM->PC,u,vx,vx);
copy(vx,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) continue;
xgcd(_MIPP_ u,r,u,u,u);
mad(_MIPP_ s,c,f,r,r,d);
mad(_MIPP_ u,d,u,r,r,d);
} while (size(d)==0);
if (res==0)
{
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,12);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int ECPVP_DSA(BOOL (*idle)(void),ecp_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,r,a,b,gx,gy,wx,wy,f,c,d,h2;
int bit,err,res=0;
epoint *G,*WP,*P;
BOOL compressed,valid;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(12)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 12);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
r=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
f=mirvar_mem(_MIPP_ mem, 8);
c=mirvar_mem(_MIPP_ mem, 9);
d=mirvar_mem(_MIPP_ mem, 10);
h2=mirvar_mem(_MIPP_ mem,11);
OS2FEP(_MIPP_ &DOM->Q,q);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
OS2FEP(_MIPP_ F,f);
if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<1 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
xgcd(_MIPP_ d,r,d,d,d);
mad(_MIPP_ f,d,f,r,r,f);
mad(_MIPP_ c,d,c,r,r,h2);
ecurve_init(_MIPP_ a,b,q,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint_set(_MIPP_ wx,wy,0,WP);
else valid=epoint_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve_mult2(_MIPP_ f,G,h2,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint_get(_MIPP_ P,d,d);
divide(_MIPP_ d,r,r);
if (mr_compare(d,c)!=0) res=MR_P1363_INVALID;
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,12);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(12));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** EC GF(2^m) primitives - support functions ***/
/* destroy the EC GF(2^m) domain structure */
P1363_API void EC2_DOMAIN_KILL(ec2_domain *DOM)
{
OCTET_KILL(&DOM->A);
OCTET_KILL(&DOM->B);
OCTET_KILL(&DOM->R);
OCTET_KILL(&DOM->Gx);
OCTET_KILL(&DOM->Gy);
OCTET_KILL(&DOM->K);
OCTET_KILL(&DOM->IK);
#ifndef MR_STATIC
if (DOM->PC.window!=0)
ebrick2_end(&DOM->PC);
#endif
DOM->words=DOM->fsize=0; DOM->H=DOM->rbits=0;
DOM->a=0; DOM->b=0; DOM->c=0;
}
/* Initialise the EC GF(2^m) domain structure
* It is assumed that the EC domain details are obtained from a file
* or from an array of strings
* multiprecision numbers are read in in Hex
* A suitable file can be generated offline by the MIRACL example program
* schoof2.exe
* Set precompute=window size if a precomputed table is to be used to
* speed up the calculation x.G mod EC(2^m)
* Returns field size in bytes */
P1363_API int EC2_DOMAIN_INIT(ec2_domain *DOM,char *fname,char **params,int precompute)
{ /* get domain details from specified file */
/* If input from a file, params=NULL, if input from strings, fname=NULL */
/* return max. size in bytes of octet strings */
FILE *fp;
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
#endif
miracl *mr_mip;
BOOL fileinput=TRUE;
big q,r,gx,gy,a,b,k;
int aa,bb,cc,bits,rbits,bytes,err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(7)];
memset(mem,0,MR_BIG_RESERVE(7));
#endif
if (fname==NULL && params==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
if (fname==NULL) fileinput=FALSE;
if (fileinput)
{
fp=fopen(fname,"rt");
if (fp==NULL) return MR_P1363_DOMAIN_NOT_FOUND;
fscanf(fp,"%d\n",&bits);
}
else
sscanf(params[0],"%d\n",&bits);
DOM->words=MR_ROUNDUP(mr_abs(bits),MIRACL);
#ifdef MR_GENERIC_AND_STATIC
mr_mip=mirsys(&instance,MR_ROUNDUP(mr_abs(bits),4),16);
#else
mr_mip=mirsys(MR_ROUNDUP(mr_abs(bits),4),16);
#endif
if (mr_mip==NULL)
{
if (fileinput) fclose(fp);
return MR_P1363_OUT_OF_MEMORY;
}
mr_mip->ERCON=TRUE;
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
q=mirvar_mem(_MIPP_ mem, 0);
r=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
a=mirvar_mem(_MIPP_ mem, 4);
b=mirvar_mem(_MIPP_ mem, 5);
k=mirvar_mem(_MIPP_ mem, 6);
bytes=MR_ROUNDUP(mr_abs(bits),8);
if (fileinput)
{
innum(_MIPP_ a,fp);
innum(_MIPP_ b,fp);
innum(_MIPP_ r,fp);
innum(_MIPP_ gx,fp);
innum(_MIPP_ gy,fp);
fscanf(fp,"%d\n",&aa);
fscanf(fp,"%d\n",&bb);
fscanf(fp,"%d\n",&cc);
fclose(fp);
}
else
{
instr(_MIPP_ a,params[1]);
instr(_MIPP_ b,params[2]);
instr(_MIPP_ r,params[3]);
instr(_MIPP_ gx,params[4]);
instr(_MIPP_ gy,params[5]);
sscanf(params[6],"%d\n",&aa);
sscanf(params[7],"%d\n",&bb);
sscanf(params[8],"%d\n",&cc);
}
DOM->M=bits;
OCTET_INIT(&DOM->A,bytes);
OCTET_INIT(&DOM->B,bytes);
OCTET_INIT(&DOM->R,bytes);
OCTET_INIT(&DOM->Gx,bytes);
OCTET_INIT(&DOM->Gy,bytes);
OCTET_INIT(&DOM->K,bytes);
OCTET_INIT(&DOM->IK,bytes);
rbits=logb2(_MIPP_ r);
DOM->H=(1+rbits)/2;
DOM->fsize=bytes;
DOM->rbits=rbits;
DOM->a=aa; DOM->b=bb; DOM->c=cc;
expb2(_MIPP_ mr_abs(bits),q); /* q=2^m */
nroot(_MIPP_ q,2,k);
premult(_MIPP_ k,2,k);
add(_MIPP_ k,q,k);
incr(_MIPP_ k,3,k);
divide(_MIPP_ k,r,k); /* gets co-factor k */
convert_big_octet(_MIPP_ a,&DOM->A);
convert_big_octet(_MIPP_ b,&DOM->B);
convert_big_octet(_MIPP_ r,&DOM->R);
convert_big_octet(_MIPP_ gx,&DOM->Gx);
convert_big_octet(_MIPP_ gy,&DOM->Gy);
convert_big_octet(_MIPP_ k,&DOM->K);
xgcd(_MIPP_ k,r,k,k,k);
convert_big_octet(_MIPP_ k,&DOM->IK);
DOM->PC.window=0;
#ifndef MR_STATIC
if (precompute)
ebrick2_init(_MIPP_ &DOM->PC,gx,gy,a,b,bits,aa,bb,cc,precompute,logb2(_MIPP_ r));
#endif
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
#else
memset(mem,0,MR_BIG_RESERVE(7));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
if (res<0) return res;
else return bytes;
}
/* validate EC GF(2^m) domain details - good idea if you got them from
* some-one else! */
P1363_API int EC2_DOMAIN_VALIDATE(BOOL (*idle)(void),ec2_domain *DOM)
{ /* do domain checks - A16.8 */
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big q,a,b,r,gx,gy,t;
epoint *G;
int i,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(7)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
mr_mip->NTRY=50;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
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);
t=mirvar_mem(_MIPP_ mem, 6);
expb2(_MIPP_ DOM->M,q);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
aa=DOM->a;
bb=DOM->b;
cc=DOM->c;
nroot(_MIPP_ q,2,t);
premult(_MIPP_ t,4,t);
if (mr_compare(r,t)<=0) res=MR_P1363_DOMAIN_ERROR;
if (size(r)<3 || size(b)==0) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
gprime(_MIPP_ 10000);
if (!isprime(_MIPP_ r)) res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
if (!ecurve2_init(_MIPP_ DOM->M,aa,bb,cc,a,b,TRUE,MR_AFFINE))
res=MR_P1363_DOMAIN_ERROR;
}
if (res==0)
{
G=epoint_init_mem(_MIPP_ mem1,0);
if (!epoint2_set(_MIPP_ gx,gy,0,G)) res=MR_P1363_DOMAIN_ERROR;
if (G->marker==MR_EPOINT_INFINITY) res=MR_P1363_DOMAIN_ERROR;
else
{
ecurve2_mult(_MIPP_ r,G,G);
if (G->marker!=MR_EPOINT_INFINITY) res=MR_P1363_DOMAIN_ERROR;
}
}
if (res==0)
{ /* MOV conditon */
convert(_MIPP_ 1,t);
for (i=0;i<50;i++)
{
mad(_MIPP_ t,q,q,r,r,t);
if (size(t)==1)
{
res=MR_P1363_DOMAIN_ERROR;
break;
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* validate an EC GF(2^m) public key W. Set full=TRUE for fuller,
* but more time-consuming test */
P1363_API int EC2_PUBLIC_KEY_VALIDATE(BOOL (*idle)(void),ec2_domain *DOM,BOOL full,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,r,wx,wy;
epoint *WP;
BOOL compressed,valid;
int bit,M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(5)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(5));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 5);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
r=mirvar_mem(_MIPP_ mem, 2);
wx=mirvar_mem(_MIPP_ mem, 3);
wy=mirvar_mem(_MIPP_ mem, 4);
M=DOM->M;
aa=DOM->a;
bb=DOM->b;
cc=DOM->c;
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (W->lenfsize+1 || W->len>2*DOM->fsize+1) res=MR_P1363_INVALID_PUBLIC_KEY;
if (logb2(_MIPP_ wx)>M || logb2(_MIPP_ wy)>M) res=MR_P1363_INVALID_PUBLIC_KEY;
}
if (res==0)
{
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
WP=epoint_init_mem(_MIPP_ mem1,0);
if (!compressed)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid || WP->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
if (res==0 && full)
{
ecurve2_mult(_MIPP_ r,WP,WP);
if (WP->marker!=MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,5);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(5));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/* Calculate a public/private EC GF(2^m) key pair. W=S.g mod EC(2^m),
* where S is the secret key and W is the public key
* Returns a single bit which can be used for "point compression"
* If RNG is NULL then the private key is provided externally in S
* otherwise it is generated randomly internally
* (Set Wy to NULL if y-coordinate not needed) */
P1363_API int EC2_KEY_PAIR_GENERATE(BOOL (*idle)(void),ec2_domain *DOM,csprng *RNG,octet*S,BOOL compress,octet *W)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,r,gx,gy,s,wx,wy;
epoint *G,*WP;
int M,aa,bb,cc;
int bit,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(8)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
r=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
s=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
M=DOM->M;
aa=DOM->a;
bb=DOM->b;
cc=DOM->c;
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
epoint2_set(_MIPP_ gx,gy,0,G);
if (RNG!=NULL)
{
strong_bigrand(_MIPP_ RNG,r,s);
}
else
{
OS2FEP(_MIPP_ S,s);
divide(_MIPP_ s,r,r);
}
if (DOM->PC.window==0)
{
ecurve2_mult(_MIPP_ s,G,WP);
bit=epoint2_get(_MIPP_ WP,wx,wy);
}
else
bit=mul2_brick(_MIPP_ &DOM->PC,s,wx,wy);
if (RNG!=NULL)
convert_big_octet(_MIPP_ s,S);
EC2OSP(_MIPP_ wx,wy,bit,compress,DOM->fsize,W);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(8));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** P1363 EC GF(2^m) primitives ***/
/* See P1363 documentation for specification */
/* Note the support for point compression */
P1363_API int EC2SVDP_DH(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *WD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,s,wx,wy,z;
BOOL compress,valid;
epoint *WP;
int bit,M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(6)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(6));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 6);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
s=mirvar_mem(_MIPP_ mem, 2);
wx=mirvar_mem(_MIPP_ mem, 3);
wy=mirvar_mem(_MIPP_ mem, 4);
z=mirvar_mem(_MIPP_ mem, 5);
M=DOM->M;
aa=DOM->a;
bb=DOM->b;
cc=DOM->c;
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ S,s);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
WP=epoint_init_mem(_MIPP_ mem1,0);
compress=OS2ECP(_MIPP_ WD,wx,wy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve2_mult(_MIPP_ s,WP,WP);
if (WP->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint2_get(_MIPP_ WP,z,z);
convert_big_octet(_MIPP_ z,Z);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,6);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(6));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SVDP_DHC(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *WD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,r,s,wx,wy,z,k,ik,t;
BOOL compress,valid;
epoint *WP;
int bit,M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(1)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 10);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 1);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
r=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
wx=mirvar_mem(_MIPP_ mem,4);
wy=mirvar_mem(_MIPP_ mem,5);
k=mirvar_mem(_MIPP_ mem, 6);
ik=mirvar_mem(_MIPP_ mem,7);
z=mirvar_mem(_MIPP_ mem, 8);
t=mirvar_mem(_MIPP_ mem, 9);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ S,s);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ ik,s,ik,r,r,t); /* t=s/k mod r */
}
else copy(s,t);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
WP=epoint_init_mem(_MIPP_ mem1,0);
compress=OS2ECP(_MIPP_ WD,wx,wy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
multiply(_MIPP_ t,k,t);
ecurve2_mult(_MIPP_ t,WP,WP);
if (WP->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint2_get(_MIPP_ WP,z,z);
convert_big_octet(_MIPP_ z,Z);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,1);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(1));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SVDP_MQV(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,r,s,u,vx,wdx,wdy,vdx,vdy,z,e,t,td;
epoint *P,*WDP,*VDP;
BOOL compress,valid;
int bit,M,aa,bb,cc,h,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(14)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(14));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 14);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
r=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
u=mirvar_mem(_MIPP_ mem, 4);
vx=mirvar_mem(_MIPP_ mem, 5);
wdx=mirvar_mem(_MIPP_ mem, 6);
wdy=mirvar_mem(_MIPP_ mem, 7);
vdx=mirvar_mem(_MIPP_ mem, 8);
vdy=mirvar_mem(_MIPP_ mem, 9);
z=mirvar_mem(_MIPP_ mem, 10);
e=mirvar_mem(_MIPP_ mem, 11);
t=mirvar_mem(_MIPP_ mem, 12);
td=mirvar_mem(_MIPP_ mem, 13);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
P=epoint_init_mem(_MIPP_ mem1,0);
OS2ECP(_MIPP_ V,vx,NULL,DOM->fsize,&bit);
WDP=epoint_init_mem(_MIPP_ mem1,1);
compress=OS2ECP(_MIPP_ WD,wdx,wdy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wdx,wdy,0,WDP);
else valid=epoint2_set(_MIPP_ wdx,wdx,bit,WDP);
if (!valid) res=MR_P1363_ERROR;
else
{
VDP=epoint_init_mem(_MIPP_ mem1,2);
compress=OS2ECP(_MIPP_ VD,vdx,vdy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ vdx,vdy,0,VDP);
else valid=epoint2_set(_MIPP_ vdx,vdx,bit,VDP);
if (!valid) res=MR_P1363_ERROR;
else
{
h=DOM->H;
expb2(_MIPP_ h,z);
copy(vx,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy (vdx,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
ecurve2_mult2(_MIPP_ e,VDP,t,WDP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_ERROR;
else
{
epoint2_get(_MIPP_ P,z,z);
convert_big_octet(_MIPP_ z,Z);
}
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,14);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(14));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SVDP_MQVC(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *U,octet *V,octet *WD,octet *VD,BOOL compatible,octet *Z)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,r,s,u,vx,wdx,wdy,vdx,vdy,z,e,t,td,k,ik;
epoint *P,*WDP,*VDP;
BOOL compress,valid;
int bit,M,aa,bb,cc,h,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(16)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(16));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 16);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
r=mirvar_mem(_MIPP_ mem, 2);
ik=mirvar_mem(_MIPP_ mem, 3);
k=mirvar_mem(_MIPP_ mem, 4);
s=mirvar_mem(_MIPP_ mem, 5);
u=mirvar_mem(_MIPP_ mem, 6);
vx=mirvar_mem(_MIPP_ mem, 7);
wdx=mirvar_mem(_MIPP_ mem, 8);
wdy=mirvar_mem(_MIPP_ mem, 9);
vdx=mirvar_mem(_MIPP_ mem, 10);
vdy=mirvar_mem(_MIPP_ mem, 11);
z=mirvar_mem(_MIPP_ mem, 12);
e=mirvar_mem(_MIPP_ mem, 13);
t=mirvar_mem(_MIPP_ mem, 14);
td=mirvar_mem(_MIPP_ mem, 15);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->K,k);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
P=epoint_init_mem(_MIPP_ mem1,0);
OS2ECP(_MIPP_ V,vx,NULL,DOM->fsize,&bit);
WDP=epoint_init_mem(_MIPP_ mem1,1);
compress=OS2ECP(_MIPP_ WD,wdx,wdy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wdx,wdy,0,WDP);
else valid=epoint2_set(_MIPP_ wdx,wdx,bit,WDP);
if (!valid) res=MR_P1363_ERROR;
else
{
VDP=epoint_init_mem(_MIPP_ mem1,2);
compress=OS2ECP(_MIPP_ VD,vdx,vdy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ vdx,vdy,0,VDP);
else valid=epoint2_set(_MIPP_ vdx,vdx,bit,VDP);
if (!valid) res=MR_P1363_ERROR;
else
{
h=DOM->H;
expb2(_MIPP_ h,z);
copy(vx,t);
divide(_MIPP_ t,z,z);
add(_MIPP_ t,z,t);
copy (vdx,td);
divide(_MIPP_ td,z,z);
add(_MIPP_ td,z,td);
mad(_MIPP_ t,s,u,r,r,e);
if (compatible)
{
OS2FEP(_MIPP_ &DOM->IK,ik);
mad(_MIPP_ e,ik,e,r,r,e);
}
mad(_MIPP_ e,k,e,r,r,e);
mad(_MIPP_ e,td,td,r,r,t);
ecurve2_mult2(_MIPP_ e,VDP,t,WDP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID_PUBLIC_KEY;
else
{
epoint2_get(_MIPP_ P,z,z);
convert_big_octet(_MIPP_ z,Z);
}
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,16);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(16));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SP_NR(BOOL (*idle)(void),ec2_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,gx,gy,r,s,f,c,d,u,vx;
epoint *G,*V;
int M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
r=mirvar_mem(_MIPP_ mem, 4);
s=mirvar_mem(_MIPP_ mem, 5);
f=mirvar_mem(_MIPP_ mem, 6);
c=mirvar_mem(_MIPP_ mem, 7);
d=mirvar_mem(_MIPP_ mem, 8);
u=mirvar_mem(_MIPP_ mem, 9);
vx=mirvar_mem(_MIPP_ mem, 10);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
V=epoint_init_mem(_MIPP_ mem1,1);
epoint2_set(_MIPP_ gx,gy,0,G);
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve2_mult(_MIPP_ u,G,V);
epoint2_get(_MIPP_ V,vx,vx);
}
else
mul2_brick(_MIPP_ &DOM->PC,u,vx,vx);
divide(_MIPP_ vx,r,r);
add(_MIPP_ vx,f,c);
divide(_MIPP_ c,r,r);
} while (size(c)==0);
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2VP_NR(BOOL (*idle)(void),ec2_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,a,b,gx,gy,wx,wy,f,c,d;
int bit,M,aa,bb,cc,err,res=0;
epoint *G,*WP,*P;
BOOL compress,valid;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 10);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
r=mirvar_mem(_MIPP_ mem, 4);
wx=mirvar_mem(_MIPP_ mem, 5);
wy=mirvar_mem(_MIPP_ mem, 6);
f=mirvar_mem(_MIPP_ mem, 7);
c=mirvar_mem(_MIPP_ mem, 8);
d=mirvar_mem(_MIPP_ mem, 9);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<0 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint2_set(_MIPP_ gx,gy,0,G);
compress=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve2_mult2(_MIPP_ d,G,c,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint2_get(_MIPP_ P,f,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SP_DSA(BOOL (*idle)(void),ec2_domain *DOM,csprng *RNG,octet *S,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,gx,gy,r,s,f,c,d,u,vx;
epoint *G,*V;
int M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 2);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
r=mirvar_mem(_MIPP_ mem, 4);
s=mirvar_mem(_MIPP_ mem, 5);
f=mirvar_mem(_MIPP_ mem, 6);
c=mirvar_mem(_MIPP_ mem, 7);
d=mirvar_mem(_MIPP_ mem, 8);
u=mirvar_mem(_MIPP_ mem, 9);
vx=mirvar_mem(_MIPP_ mem, 10);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
V=epoint_init_mem(_MIPP_ mem1,1);
epoint2_set(_MIPP_ gx,gy,0,G);
do {
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve2_mult(_MIPP_ u,G,V);
epoint2_get(_MIPP_ V,vx,vx);
}
else
mul2_brick(_MIPP_ &DOM->PC,u,vx,vx);
copy(vx,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) continue;
xgcd(_MIPP_ u,r,u,u,u);
mad(_MIPP_ s,c,f,r,r,d);
mad(_MIPP_ u,d,u,r,r,d);
} while (size(d)==0);
if (res==0)
{
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2VP_DSA(BOOL (*idle)(void),ec2_domain *DOM,octet *W,octet *C,octet *D,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,a,b,gx,gy,wx,wy,f,c,d,h2;
int bit,M,aa,bb,cc,err,res=0;
epoint *G,*WP,*P;
BOOL compress,valid;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
r=mirvar_mem(_MIPP_ mem, 4);
wx=mirvar_mem(_MIPP_ mem, 5);
wy=mirvar_mem(_MIPP_ mem, 6);
f=mirvar_mem(_MIPP_ mem, 7);
c=mirvar_mem(_MIPP_ mem, 8);
d=mirvar_mem(_MIPP_ mem, 9);
h2=mirvar_mem(_MIPP_ mem, 10);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
OS2FEP(_MIPP_ F,f);
if (size(c)<1 || mr_compare(c,r)>=0 || size(d)<1 || mr_compare(d,r)>=0)
res=MR_P1363_INVALID;
}
if (res==0)
{
xgcd(_MIPP_ d,r,d,d,d);
mad(_MIPP_ f,d,f,r,r,f);
mad(_MIPP_ c,d,c,r,r,h2);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint2_set(_MIPP_ gx,gy,0,G);
compress=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compress)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve2_mult2(_MIPP_ f,G,h2,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint2_get(_MIPP_ P,d,d);
divide(_MIPP_ d,r,r);
if (mr_compare(d,c)!=0) res=MR_P1363_INVALID;
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2PSP_NR2PV(BOOL (*idle)(void),ec2_domain *DOM,csprng *RNG,octet *U,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big a,b,gx,gy,r,u,vx;
epoint *G,*VP;
int M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(7)];
char mem1[MR_ECP_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
a=mirvar_mem(_MIPP_ mem, 0);
b=mirvar_mem(_MIPP_ mem, 1);
gx=mirvar_mem(_MIPP_ mem, 2);
gy=mirvar_mem(_MIPP_ mem, 3);
r=mirvar_mem(_MIPP_ mem, 4);
u=mirvar_mem(_MIPP_ mem, 5);
vx=mirvar_mem(_MIPP_ mem, 6);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
VP=epoint_init_mem(_MIPP_ mem1,1);
epoint2_set(_MIPP_ gx,gy,0,G);
strong_bigrand(_MIPP_ RNG,r,u);
if (DOM->PC.window==0)
{
ecurve2_mult(_MIPP_ u,G,VP);
epoint2_get(_MIPP_ VP,vx,vx);
}
else
mul2_brick(_MIPP_ &DOM->PC,u,vx,vx);
convert_big_octet(_MIPP_ u,U);
FE2OSP(_MIPP_ vx,DOM->fsize,V);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
ecp_memkill(_MIPP_ mem1,2);
#else
memset(mem,0,MR_BIG_RESERVE(7));
memset(mem1,0,MR_ECP_RESERVE(2));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SP_NR2(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *U,octet *V,octet *F,octet *C,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,u,v,s,c,d,f;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(7)];
memset(mem,0,MR_BIG_RESERVE(7));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 7);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
r=mirvar_mem(_MIPP_ mem, 0);
u=mirvar_mem(_MIPP_ mem, 1);
v=mirvar_mem(_MIPP_ mem, 2);
s=mirvar_mem(_MIPP_ mem, 3);
c=mirvar_mem(_MIPP_ mem, 4);
d=mirvar_mem(_MIPP_ mem, 5);
f=mirvar_mem(_MIPP_ mem, 6);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ F,f);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ V,v);
if (size(u)<1 || mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
if (size(v)<1) res=MR_P1363_BAD_ASSUMPTION;
if (mr_compare(f,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
add(_MIPP_ v,f,c);
divide(_MIPP_ c,r,r);
if (size(c)==0) res=MR_P1363_ERROR;
}
if (res==0)
{
mad(_MIPP_ s,c,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ c,C);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,7);
#else
memset(mem,0,MR_BIG_RESERVE(7));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2VP_NR2(BOOL (*idle)(void),ec2_domain *DOM,octet *W,octet *C,octet *D,octet *F,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,a,b,gx,gy,v,wx,wy,c,d,f;
epoint *G,*WP,*P;
BOOL compressed,valid;
int bit,M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(11)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 11);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
r=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
v=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
c=mirvar_mem(_MIPP_ mem, 8);
d=mirvar_mem(_MIPP_ mem, 9);
f=mirvar_mem(_MIPP_ mem, 10);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ C,c);
OS2FEP(_MIPP_ D,d);
if (size(c)<1 || mr_compare(c,r)>=0 || mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint2_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve2_mult2(_MIPP_ d,G,c,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint2_get(_MIPP_ P,v,v);
copy(v,f);
divide(_MIPP_ f,r,r);
subtract(_MIPP_ c,f,f);
if (size(f)<0) add(_MIPP_ f,r,f);
convert_big_octet(_MIPP_ f,F);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,11);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(11));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2SP_PV(BOOL (*idle)(void),ec2_domain *DOM,octet *S,octet *U,octet *H,octet *D)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,u,s,d,h;
int err,res=0;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(5)];
memset(mem,0,MR_BIG_RESERVE(5));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 5);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
r=mirvar_mem(_MIPP_ mem, 0);
u=mirvar_mem(_MIPP_ mem, 1);
s=mirvar_mem(_MIPP_ mem, 2);
d=mirvar_mem(_MIPP_ mem, 3);
h=mirvar_mem(_MIPP_ mem, 4);
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ S,s);
OS2FEP(_MIPP_ U,u);
OS2FEP(_MIPP_ H,h);
if (size(u)<1 || mr_compare(u,r)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
mad(_MIPP_ s,h,s,r,r,d);
subtract(_MIPP_ u,d,d);
if (size(d)<0) add(_MIPP_ d,r,d);
convert_big_octet(_MIPP_ d,D);
}
OCTET_CLEAR(U);
#ifndef MR_STATIC
memkill(_MIPP_ mem,5);
#else
memset(mem,0,MR_BIG_RESERVE(5));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int EC2VP_PV(BOOL (*idle)(void),ec2_domain *DOM,octet *W,octet *H,octet *D,octet *V)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,DOM->words,0);
#else
miracl *mr_mip=mirsys(DOM->words,0);
#endif
big r,a,b,gx,gy,v,wx,wy,d,h;
epoint *G,*WP,*P;
BOOL compressed,valid;
int bit,M,aa,bb,cc,err,res=0;
#ifndef MR_STATIC
char *mem;
char *mem1;
#else
char mem[MR_BIG_RESERVE(10)];
char mem1[MR_ECP_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 10);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
mem1=(char *)ecp_memalloc(_MIPP_ 3);
if (mem1==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
r=mirvar_mem(_MIPP_ mem, 0);
a=mirvar_mem(_MIPP_ mem, 1);
b=mirvar_mem(_MIPP_ mem, 2);
gx=mirvar_mem(_MIPP_ mem, 3);
gy=mirvar_mem(_MIPP_ mem, 4);
v=mirvar_mem(_MIPP_ mem, 5);
wx=mirvar_mem(_MIPP_ mem, 6);
wy=mirvar_mem(_MIPP_ mem, 7);
d=mirvar_mem(_MIPP_ mem, 8);
h=mirvar_mem(_MIPP_ mem, 9);
M=DOM->M;
aa=DOM->a; bb=DOM->b; cc=DOM->c;
OS2FEP(_MIPP_ &DOM->R,r);
OS2FEP(_MIPP_ &DOM->Gx,gx);
OS2FEP(_MIPP_ &DOM->Gy,gy);
OS2FEP(_MIPP_ &DOM->B,b);
OS2FEP(_MIPP_ &DOM->A,a);
OS2FEP(_MIPP_ H,h);
OS2FEP(_MIPP_ D,d);
if (mr_compare(d,r)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
ecurve2_init(_MIPP_ M,aa,bb,cc,a,b,FALSE,MR_PROJECTIVE);
G=epoint_init_mem(_MIPP_ mem1,0);
WP=epoint_init_mem(_MIPP_ mem1,1);
P=epoint_init_mem(_MIPP_ mem1,2);
epoint2_set(_MIPP_ gx,gy,0,G);
compressed=OS2ECP(_MIPP_ W,wx,wy,DOM->fsize,&bit);
if (!compressed)
valid=epoint2_set(_MIPP_ wx,wy,0,WP);
else valid=epoint2_set(_MIPP_ wx,wx,bit,WP);
if (!valid) res=MR_P1363_ERROR;
else
{
ecurve2_mult2(_MIPP_ d,G,h,WP,P);
if (P->marker==MR_EPOINT_INFINITY) res=MR_P1363_INVALID;
else
{
epoint2_get(_MIPP_ P,v,v);
FE2OSP(_MIPP_ v,DOM->fsize,V);
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
ecp_memkill(_MIPP_ mem1,3);
#else
memset(mem,0,MR_BIG_RESERVE(10));
memset(mem1,0,MR_ECP_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
/*** RSA/RW primitives - support functions ***/
/* destroy the Public Key structure */
P1363_API void IF_PUBLIC_KEY_KILL(if_public_key *PUB)
{
OCTET_KILL(&PUB->N);
PUB->words=PUB->fsize=0; PUB->e=0;
}
/* destroy the Private Key structure */
P1363_API void IF_PRIVATE_KEY_KILL(if_private_key *PRIV)
{
OCTET_KILL(&PRIV->P);
OCTET_KILL(&PRIV->Q);
OCTET_KILL(&PRIV->DP);
OCTET_KILL(&PRIV->DQ);
OCTET_KILL(&PRIV->C);
PRIV->words=0;
}
/* generate an RSA/RW key pair. The size of the public key in bits
* is passed as a parameter. If the exponent E is even, then an RW key pair
* is generated, otherwise an RSA key pair */
P1363_API int IF_KEY_PAIR(BOOL (*idle)(void),csprng *RNG,int bits,int E,if_private_key *PRIV,if_public_key *PUB)
{ /* A16.11/A16.12 more or less */
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
#endif
miracl *mr_mip;
int hE,m,r,bytes,hbytes,words,err,res=0;
big p,q,dp,dq,c,n,t,p1,q1;
BOOL RW;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(9)];
memset(mem,0,MR_BIG_RESERVE(9));
#endif
words=MR_ROUNDUP(bits,MIRACL);
#ifdef MR_GENERIC_AND_STATIC
mr_mip=mirsys(&instance,words,0);
#else
mr_mip=mirsys(words,0);
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
mr_mip->NTRY=50;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
p=mirvar_mem(_MIPP_ mem, 0);
q=mirvar_mem(_MIPP_ mem, 1);
dp=mirvar_mem(_MIPP_ mem, 2);
dq=mirvar_mem(_MIPP_ mem, 3);
c=mirvar_mem(_MIPP_ mem, 4);
n=mirvar_mem(_MIPP_ mem, 5);
p1=mirvar_mem(_MIPP_ mem, 6);
q1=mirvar_mem(_MIPP_ mem, 7);
t=mirvar_mem(_MIPP_ mem, 8);
RW=FALSE;
if (E%2==0)
{
RW=TRUE; /* Rabin-Williams */
hE=E/2;
}
PRIV->words=words;
PUB->words=words;
PUB->e=E;
bytes=MR_ROUNDUP(bits,8);
PUB->fsize=bytes;
OCTET_INIT(&PUB->N,bytes);
hbytes=2+(bytes/2);
OCTET_INIT(&PRIV->P,hbytes);
OCTET_INIT(&PRIV->Q,hbytes);
OCTET_INIT(&PRIV->DP,hbytes);
OCTET_INIT(&PRIV->DQ,hbytes);
OCTET_INIT(&PRIV->C,hbytes);
gprime(_MIPP_ 10000);
forever
{
if (mr_mip->ERNUM) break;
m=(bits+1)/2;
expb2(_MIPP_ m,t);
do
{
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,t,p);
} while (logb2(_MIPP_ p)ERNUM) break;
if (RW) incr(_MIPP_ p,6,p);
incr(_MIPP_ p,1,p);
if (RW)
{
if (hE==1) r=1;
else r=remain(_MIPP_ p,hE);
}
else r=remain(_MIPP_ p,E);
incr(_MIPP_ p,1,p);
if (r==0) continue;
} while (!isprime(_MIPP_ p));
expb2(_MIPP_ bits,t);
divide(_MIPP_ t,p,t);
expb2(_MIPP_ bits-1,c);
divide(_MIPP_ c,p,c);
incr(_MIPP_ c,1,c);
do
{
if (mr_mip->ERNUM) break;
strong_bigrand(_MIPP_ RNG,t,q);
} while (mr_compare(q,c)<0);
if (remain(_MIPP_ q,2)==0) incr(_MIPP_ q,1,q);
if (RW)
{ /* make q=7 mod 8 */
r=remain(_MIPP_ q,8);
incr(_MIPP_ q,(7-r)%8,q);
}
do
{
if (mr_mip->ERNUM) break;
if (RW) incr(_MIPP_ q,6,q);
incr(_MIPP_ q,1,q);
if (RW)
{
if (hE==1) r=1;
else r=remain(_MIPP_ q,hE);
}
else r=remain(_MIPP_ q,E);
incr(_MIPP_ q,1,q);
if (r==0) continue;
} while (!isprime(_MIPP_ q));
multiply(_MIPP_ p,q,n);
if (logb2(_MIPP_ n)!=bits) continue; /* very rare! */
decr(_MIPP_ p,1,p1);
decr(_MIPP_ q,1,q1);
multiply(_MIPP_ p1,q1,c);
egcd(_MIPP_ p1,q1,t);
divide(_MIPP_ c,t,c); /* c=LCM(p-1,q-1) */
if (RW) subdiv(_MIPP_ c,2,c);
convert(_MIPP_ E,t);
if (xgcd(_MIPP_ t,c,dp,dp,dp)!=1) continue;
break;
}
copy(dp,dq);
divide(_MIPP_ dp,p1,p1);
divide(_MIPP_ dq,q1,q1);
xgcd(_MIPP_ q,p,c,c,c); /* c=1/q mod p */
convert_big_octet(_MIPP_ n,&PUB->N);
convert_big_octet(_MIPP_ p,&PRIV->P);
convert_big_octet(_MIPP_ q,&PRIV->Q);
convert_big_octet(_MIPP_ dp,&PRIV->DP);
convert_big_octet(_MIPP_ dq,&PRIV->DQ);
convert_big_octet(_MIPP_ c,&PRIV->C);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
#else
memset(mem,0,MR_BIG_RESERVE(9));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
if (res<0) return res;
else return bytes;
}
static void private_key_op(_MIPD_ big p,big q,big dp,big dq,big c,big i,big s)
{ /* internal:- basic RSA/RW decryption operation */
big jp,jq;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(2)];
memset(mem,0,MR_BIG_RESERVE(2));
#endif
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 2);
#endif
jp=mirvar_mem(_MIPP_ mem,0);
jq=mirvar_mem(_MIPP_ mem,1);
powmod(_MIPP_ i,dp,p,jp);
powmod(_MIPP_ i,dq,q,jq);
subtract(_MIPP_ jp,jq,jp);
mad(_MIPP_ c,jp,jp,p,p,s);
if (size(s)<0) add(_MIPP_ s,p,s);
multiply(_MIPP_ s,q,jp);
add(_MIPP_ jq,jp,s);
#ifndef MR_STATIC
memkill(_MIPP_ mem,2);
#else
memset(mem,0,MR_BIG_RESERVE(2));
#endif
}
/*** P1363 RSA/RW primitives ***/
/* See P1363 documentation for more details */
P1363_API int IFEP_RSA(BOOL (*idle)(void),if_public_key *PUB,octet *F,octet *G)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PUB->words,0);
#else
miracl *mr_mip=mirsys(PUB->words,0);
#endif
int e,err,res=0;
big f,g,n;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 3);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
f=mirvar_mem(_MIPP_ mem, 0);
g=mirvar_mem(_MIPP_ mem, 1);
n=mirvar_mem(_MIPP_ mem, 2);
OS2FEP(_MIPP_ &PUB->N,n);
OS2FEP(_MIPP_ F,f);
if (mr_compare(f,n)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
e=PUB->e;
power(_MIPP_ f,e,n,g);
convert_big_octet(_MIPP_ g,G);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,3);
#else
memset(mem,0,MR_BIG_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFDP_RSA(BOOL (*idle)(void),if_private_key *PRIV,octet *G,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PRIV->words,0);
#else
miracl *mr_mip=mirsys(PRIV->words,0);
#endif
int err,res=0;
big f,g,p,q,dp,dq,c,n;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
f=mirvar_mem(_MIPP_ mem, 0);
g=mirvar_mem(_MIPP_ mem, 1);
p=mirvar_mem(_MIPP_ mem, 2);
q=mirvar_mem(_MIPP_ mem, 3);
dp=mirvar_mem(_MIPP_ mem, 4);
dq=mirvar_mem(_MIPP_ mem, 5);
c=mirvar_mem(_MIPP_ mem, 6);
n=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &PRIV->P,p);
OS2FEP(_MIPP_ &PRIV->Q,q);
OS2FEP(_MIPP_ &PRIV->DP,dp);
OS2FEP(_MIPP_ &PRIV->DQ,dq);
OS2FEP(_MIPP_ &PRIV->C,c);
OS2FEP(_MIPP_ G,g);
multiply(_MIPP_ p,q,n);
if (mr_compare(g,n)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
private_key_op(_MIPP_ p,q,dp,dq,c,g,f);
convert_big_octet(_MIPP_ f,F);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFSP_RSA1(BOOL (*idle)(void),if_private_key *PRIV,octet *F,octet *S)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PRIV->words,0);
#else
miracl *mr_mip=mirsys(PRIV->words,0);
#endif
int err,res=0;
big f,s,p,q,dp,dq,c,n;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(8)];
memset(mem,0,MR_BIG_RESERVE(8));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 8);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
p=mirvar_mem(_MIPP_ mem, 2);
q=mirvar_mem(_MIPP_ mem, 3);
dp=mirvar_mem(_MIPP_ mem, 4);
dq=mirvar_mem(_MIPP_ mem, 5);
c=mirvar_mem(_MIPP_ mem, 6);
n=mirvar_mem(_MIPP_ mem, 7);
OS2FEP(_MIPP_ &PRIV->P,p);
OS2FEP(_MIPP_ &PRIV->Q,q);
OS2FEP(_MIPP_ &PRIV->DP,dp);
OS2FEP(_MIPP_ &PRIV->DQ,dq);
OS2FEP(_MIPP_ &PRIV->C,c);
OS2FEP(_MIPP_ F,f);
multiply(_MIPP_ p,q,n);
if (mr_compare(f,n)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
private_key_op(_MIPP_ p,q,dp,dq,c,f,s);
convert_big_octet(_MIPP_ s,S);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,8);
#else
memset(mem,0,MR_BIG_RESERVE(8));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFVP_RSA1(BOOL (*idle)(void),if_public_key *PUB,octet *S,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PUB->words,0);
#else
miracl *mr_mip=mirsys(PUB->words,0);
#endif
int e,err,res=0;
big f,s,n;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 3);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
n=mirvar_mem(_MIPP_ mem, 2);
OS2FEP(_MIPP_ &PUB->N,n);
OS2FEP(_MIPP_ S,s);
if (mr_compare(s,n)>=0) res=MR_P1363_INVALID;
}
if (res==0)
{
e=PUB->e;
power(_MIPP_ s,e,n,f);
convert_big_octet(_MIPP_ f,F);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,3);
#else
memset(mem,0,MR_BIG_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFSP_RSA2(BOOL (*idle)(void),if_private_key *PRIV,octet *F,octet *S)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PRIV->words,0);
#else
miracl *mr_mip=mirsys(PRIV->words,0);
#endif
int err,res=0;
big f,s,p,q,dp,dq,c,n,t;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(9)];
memset(mem,0,MR_BIG_RESERVE(9));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
p=mirvar_mem(_MIPP_ mem, 2);
q=mirvar_mem(_MIPP_ mem, 3);
dp=mirvar_mem(_MIPP_ mem, 4);
dq=mirvar_mem(_MIPP_ mem, 5);
c=mirvar_mem(_MIPP_ mem, 6);
n=mirvar_mem(_MIPP_ mem, 7);
t=mirvar_mem(_MIPP_ mem, 8);
OS2FEP(_MIPP_ &PRIV->P,p);
OS2FEP(_MIPP_ &PRIV->Q,q);
OS2FEP(_MIPP_ &PRIV->DP,dp);
OS2FEP(_MIPP_ &PRIV->DQ,dq);
OS2FEP(_MIPP_ &PRIV->C,c);
OS2FEP(_MIPP_ F,f);
multiply(_MIPP_ p,q,n);
if (remain(_MIPP_ f,16)!=12) res=MR_P1363_BAD_ASSUMPTION;
if (mr_compare(f,n)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
private_key_op(_MIPP_ p,q,dp,dq,c,f,s);
subtract(_MIPP_ n,s,t);
if (mr_compare(s,t)>0)
convert_big_octet(_MIPP_ t,S);
else
convert_big_octet(_MIPP_ s,S);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
#else
memset(mem,0,MR_BIG_RESERVE(9));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFVP_RSA2(BOOL (*idle)(void),if_public_key *PUB,octet *S,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PUB->words,0);
#else
miracl *mr_mip=mirsys(PUB->words,0);
#endif
int e,err,res=0;
big f,s,n;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(3)];
memset(mem,0,MR_BIG_RESERVE(3));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 3);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
n=mirvar_mem(_MIPP_ mem, 2);
OS2FEP(_MIPP_ &PUB->N,n);
OS2FEP(_MIPP_ S,s);
decr(_MIPP_ n,1,f);
subdiv(_MIPP_ f,2,f);
if (mr_compare(s,f)>0) res=MR_P1363_INVALID;
}
if (res==0)
{
e=PUB->e;
power(_MIPP_ s,e,n,f);
if (remain(_MIPP_ f,16)==12)
convert_big_octet(_MIPP_ f,F);
else
{
subtract(_MIPP_ n,f,f);
if (remain(_MIPP_ f,16)==12)
convert_big_octet(_MIPP_ f,F);
else
res=MR_P1363_INVALID;
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,3);
#else
memset(mem,0,MR_BIG_RESERVE(3));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFSP_RW(BOOL (*idle)(void),if_private_key *PRIV,octet *F,octet *S)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PRIV->words,0);
#else
miracl *mr_mip=mirsys(PRIV->words,0);
#endif
int err,res=0;
big f,s,p,q,dp,dq,c,n,t;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(9)];
memset(mem,0,MR_BIG_RESERVE(9));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 9);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
p=mirvar_mem(_MIPP_ mem, 2);
q=mirvar_mem(_MIPP_ mem, 3);
dp=mirvar_mem(_MIPP_ mem, 4);
dq=mirvar_mem(_MIPP_ mem, 5);
c=mirvar_mem(_MIPP_ mem, 6);
n=mirvar_mem(_MIPP_ mem, 7);
t=mirvar_mem(_MIPP_ mem, 8);
OS2FEP(_MIPP_ &PRIV->P,p);
OS2FEP(_MIPP_ &PRIV->Q,q);
OS2FEP(_MIPP_ &PRIV->DP,dp);
OS2FEP(_MIPP_ &PRIV->DQ,dq);
OS2FEP(_MIPP_ &PRIV->C,c);
OS2FEP(_MIPP_ F,f);
multiply(_MIPP_ p,q,n);
if (remain(_MIPP_ f,16)!=12) res=MR_P1363_BAD_ASSUMPTION;
if (mr_compare(f,n)>=0) res=MR_P1363_BAD_ASSUMPTION;
}
if (res==0)
{
if (jack(_MIPP_ f,n)!=1)
subdiv(_MIPP_ f,2,f);
private_key_op(_MIPP_ p,q,dp,dq,c,f,s);
subtract(_MIPP_ n,s,t);
if (mr_compare(s,t)>0)
convert_big_octet(_MIPP_ t,S);
else
convert_big_octet(_MIPP_ s,S);
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,9);
#else
memset(mem,0,MR_BIG_RESERVE(9));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}
P1363_API int IFVP_RW(BOOL (*idle)(void),if_public_key *PUB,octet *S,octet *F)
{
#ifdef MR_GENERIC_AND_STATIC
miracl instance;
miracl *mr_mip=mirsys(&instance,PUB->words,0);
#else
miracl *mr_mip=mirsys(PUB->words,0);
#endif
int e,err,res=0;
big f,s,n,t1,t2;
#ifndef MR_STATIC
char *mem;
#else
char mem[MR_BIG_RESERVE(5)];
memset(mem,0,MR_BIG_RESERVE(5));
#endif
if (mr_mip==NULL) return MR_P1363_OUT_OF_MEMORY;
mr_mip->ERCON=TRUE;
set_user_function(_MIPP_ idle);
#ifndef MR_STATIC
mem=(char *)memalloc(_MIPP_ 5);
if (mem==NULL) res=MR_P1363_OUT_OF_MEMORY;
#endif
if (res==0)
{
s=mirvar_mem(_MIPP_ mem, 0);
f=mirvar_mem(_MIPP_ mem, 1);
n=mirvar_mem(_MIPP_ mem, 2);
t1=mirvar_mem(_MIPP_ mem, 3);
t2=mirvar_mem(_MIPP_ mem, 4);
OS2FEP(_MIPP_ &PUB->N,n);
OS2FEP(_MIPP_ S,s);
decr(_MIPP_ n,1,f);
subdiv(_MIPP_ f,2,f);
if (mr_compare(s,f)>0) res=MR_P1363_INVALID;
}
if (res==0)
{
e=PUB->e;
power(_MIPP_ s,e,n,t1);
subtract(_MIPP_ n,t1,t2);
if (remain(_MIPP_ t1,16)==12)
convert_big_octet(_MIPP_ t1,F);
else
{
if (remain(_MIPP_ t1,8)==6)
{
premult(_MIPP_ t1,2,f);
convert_big_octet(_MIPP_ f,F);
}
else
{
if (remain(_MIPP_ t2,16)==12)
convert_big_octet(_MIPP_ t2,F);
else
{
if (remain(_MIPP_ t2,8)==6)
{
premult(_MIPP_ t2,2,f);
convert_big_octet(_MIPP_ f,F);
}
else res=MR_P1363_INVALID;
}
}
}
}
#ifndef MR_STATIC
memkill(_MIPP_ mem,5);
#else
memset(mem,0,MR_BIG_RESERVE(5));
#endif
err=mr_mip->ERNUM;
mirexit(_MIPPO_ );
if (err==MR_ERR_OUT_OF_MEMORY) return MR_P1363_OUT_OF_MEMORY;
if (err==MR_ERR_DIV_BY_ZERO) return MR_P1363_DIV_BY_ZERO;
if (err!=0) return -(1000+err);
return res;
}