534 lines
14 KiB
C
534 lines
14 KiB
C
|
|
/***************************************************************************
|
|
*
|
|
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 <http://www.gnu.org/licenses/>. *
|
|
*
|
|
You can be released from the requirements of the license by purchasing *
|
|
a commercial license. Buying such a license is mandatory as soon as you *
|
|
develop commercial activities involving the CertiVox 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 I/O routines 1.
|
|
* mrio1.c
|
|
*/
|
|
|
|
#include "miracl.h"
|
|
|
|
#ifndef MR_SIMPLE_IO
|
|
|
|
int instr(_MIPD_ flash x,char *string)
|
|
{ /* input a big number *
|
|
* returns length in digits */
|
|
int i,ipt,n,s,e,pads;
|
|
BOOL first_after_pad;
|
|
int ch,lc;
|
|
#ifdef MR_FLASH
|
|
BOOL frac;
|
|
#endif
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return 0;
|
|
|
|
MR_IN(76)
|
|
|
|
if (mr_mip->apbase==0 || mr_mip->apbase>256)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_BASE_TOO_BIG);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
|
|
if (!mr_mip->active)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_NO_MIRSYS);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
|
|
zero(x);
|
|
if (mr_mip->fin) string=mr_mip->IOBUFF;
|
|
if (mr_mip->INPLEN==0)
|
|
{ /* inputting ASCII bytes */
|
|
|
|
#ifndef MR_NO_FILE_IO
|
|
|
|
if (mr_mip->fin)
|
|
{ /* read in characters */
|
|
i=0;
|
|
do
|
|
{
|
|
ch=fgetc(mr_mip->infile);
|
|
if (ch==EOF) break;
|
|
string[i++]=ch;
|
|
|
|
if (i>=mr_mip->IOBSIZ)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_IO_OVERFLOW);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
} while (ch!='\n' && ch!='\0');
|
|
string[i]='\0';
|
|
}
|
|
|
|
#endif
|
|
forever
|
|
{ /* get input length */
|
|
ch=(unsigned char)string[mr_mip->INPLEN];
|
|
if (ch=='\0') break;
|
|
if (mr_mip->apbase<=60 && ch=='\n') break;
|
|
mr_mip->INPLEN++;
|
|
if (string==mr_mip->IOBUFF && mr_mip->INPLEN>=mr_mip->IOBSIZ)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_IO_OVERFLOW);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ /* inputting BINARY bytes */
|
|
if (string==mr_mip->IOBUFF && mr_mip->INPLEN>=mr_mip->IOBSIZ)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_IO_OVERFLOW);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
|
|
#ifndef MR_NO_FILE_IO
|
|
|
|
if (mr_mip->fin) for(i=0;i<mr_mip->INPLEN;i++)
|
|
{
|
|
if ((ch=fgetc(mr_mip->infile))==EOF)
|
|
{
|
|
mr_mip->INPLEN=i;
|
|
break;
|
|
}
|
|
string[i]=MR_TOBYTE(ch);
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
n=0;
|
|
s=PLUS;
|
|
e=0;
|
|
#ifdef MR_FLASH
|
|
frac=FALSE;
|
|
#endif
|
|
if (mr_mip->INPLEN>0 && mr_mip->apbase<=60)
|
|
{ /* skip leading blanks and check sign */
|
|
#ifdef MR_FLASH
|
|
if (string[mr_mip->INPLEN-1]=='/') mr_mip->INPLEN--;
|
|
#endif
|
|
while (string[e]==' ') e++;
|
|
if (string[e]=='-')
|
|
{ /* check sign */
|
|
s=MINUS;
|
|
e++;
|
|
}
|
|
if (string[e]=='+') e++;
|
|
}
|
|
|
|
pads=0; first_after_pad=TRUE;
|
|
for (i=mr_mip->INPLEN-1;i>=e;i--)
|
|
{
|
|
ch=(unsigned char)string[i];
|
|
if (mr_mip->apbase<=60 || mr_mip->apbase==64)
|
|
{ /* check for slash or dot and convert character to number */
|
|
#ifdef MR_FLASH
|
|
if (mr_mip->apbase<=60 && !frac)
|
|
{
|
|
if (ch=='/')
|
|
{
|
|
frac=TRUE;
|
|
copy(x,mr_mip->w0);
|
|
zero(x);
|
|
n=0;
|
|
continue;
|
|
}
|
|
if (ch=='.')
|
|
{
|
|
frac=TRUE;
|
|
zero(mr_mip->w0);
|
|
putdig(_MIPP_ 1,mr_mip->w0,n+1);
|
|
continue;
|
|
}
|
|
}
|
|
#endif
|
|
ch+=80;
|
|
if (mr_mip->apbase==64)
|
|
{ /* base64 */
|
|
if (ch<=112) continue; /* ignore white space */
|
|
if (ch>144 && ch<171) ch-=145;
|
|
if (ch>176 && ch<203) ch-=151;
|
|
if (ch>127 && ch<138) ch-=76;
|
|
if (ch==123) ch=62;
|
|
if (ch==127) ch=63;
|
|
if (ch==141) {pads++; continue;} /* pads '=' */
|
|
}
|
|
else
|
|
{
|
|
if (ch>127 && ch<138) ch-=128;
|
|
if (ch>144 && ch<171) ch-=135;
|
|
if (mr_mip->apbase<=16)
|
|
{
|
|
if (ch>176 && ch<203) ch-=167;
|
|
}
|
|
else
|
|
{
|
|
if (ch>176 && ch<203) ch-=141;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((mr_small)ch>=mr_mip->apbase || pads>2)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_BAD_FORMAT);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
|
|
if (pads && first_after_pad)
|
|
{ /* there was padding, so adjust */
|
|
lc=ch>>(2*pads);
|
|
first_after_pad=FALSE;
|
|
continue;
|
|
}
|
|
|
|
n++;
|
|
if (pads)
|
|
{
|
|
putdig(_MIPP_ 0x3f&((ch<<(6-2*pads))|lc),x,n);
|
|
lc=(ch>>(2*pads));
|
|
continue;
|
|
}
|
|
|
|
putdig(_MIPP_ ch,x,n);
|
|
}
|
|
|
|
if (pads && lc>0)
|
|
putdig(_MIPP_ lc,x,++n);
|
|
|
|
ipt=mr_mip->INPLEN;
|
|
mr_mip->INPLEN=0;
|
|
insign(s,x);
|
|
mr_lzero(x);
|
|
#ifdef MR_FLASH
|
|
mr_lzero(mr_mip->w0);
|
|
if (frac) fpack(_MIPP_ x,mr_mip->w0,x);
|
|
#endif
|
|
MR_OUT
|
|
return ipt;
|
|
}
|
|
|
|
int otstr(_MIPD_ flash x,char *string)
|
|
{ /* output a big number */
|
|
int s,i,n,ch,rp,nd,m;
|
|
BOOL check;
|
|
#ifdef MR_FLASH
|
|
int nw,dw;
|
|
#endif
|
|
mr_lentype lx;
|
|
BOOL done;
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return 0;
|
|
|
|
MR_IN(75)
|
|
if (mr_mip->apbase==0 || mr_mip->apbase>256)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_BASE_TOO_BIG);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
|
|
if (!mr_mip->active)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_NO_MIRSYS);
|
|
MR_OUT
|
|
return 0;
|
|
}
|
|
n=0;
|
|
s=exsign(x);
|
|
insign(PLUS,x);
|
|
lx = x->len;
|
|
if (lx==0 && mr_mip->apbase<=60)
|
|
{
|
|
|
|
#ifndef MR_NO_FILE_IO
|
|
|
|
if (!mr_mip->fout)
|
|
{
|
|
string[0]='0';
|
|
string[1]='\0';
|
|
}
|
|
else
|
|
{
|
|
fputc('0',mr_mip->otfile);
|
|
fputc('\n',mr_mip->otfile);
|
|
}
|
|
#else
|
|
string[0]='0';
|
|
string[1]='\0';
|
|
|
|
#endif
|
|
MR_OUT
|
|
return 1;
|
|
}
|
|
rp=0;
|
|
if (s==MINUS && mr_mip->apbase<=60)
|
|
{
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]='-';
|
|
else fputc('-',mr_mip->otfile);
|
|
#else
|
|
string[n]='-';
|
|
#endif
|
|
n++;
|
|
}
|
|
#ifdef MR_FLASH
|
|
done=FALSE;
|
|
numer(_MIPP_ x,mr_mip->w6);
|
|
if (mr_mip->RPOINT)
|
|
{ /* output with radix point */
|
|
denom(_MIPP_ x,mr_mip->w5);
|
|
if (size(mr_mip->w5)>1)
|
|
{ /* multiply up numerator to get full precision in *
|
|
* the output. Remember position of radix point. */
|
|
nw=(int)(lx&MR_MSK);
|
|
dw=(int)((lx>>MR_BTS)&MR_MSK);
|
|
if (nw==0) nw++;
|
|
check=mr_mip->check;
|
|
mr_mip->check=OFF;
|
|
if (nw>dw) mr_shift(_MIPP_ mr_mip->w5,nw-dw,mr_mip->w5);
|
|
if (dw>nw) mr_shift(_MIPP_ mr_mip->w6,dw-nw,mr_mip->w6);
|
|
nd=mr_mip->nib;
|
|
if (mr_compare(mr_mip->w6,mr_mip->w5)>=0) nd--;
|
|
copy(mr_mip->w6,mr_mip->w0);
|
|
if (((int)mr_mip->w0->len+nd)>2*mr_mip->nib) nd=2*mr_mip->nib-(int)mr_mip->w0->len;
|
|
mr_shift(_MIPP_ mr_mip->w0,nd,mr_mip->w0);
|
|
divide(_MIPP_ mr_mip->w0,mr_mip->w5,mr_mip->w6);
|
|
mr_mip->check=check;
|
|
rp=mr_mip->pack*(nd+dw-nw);
|
|
}
|
|
}
|
|
#else
|
|
copy(x,mr_mip->w6);
|
|
done=TRUE;
|
|
#endif
|
|
|
|
forever
|
|
{
|
|
nd=numdig(_MIPP_ mr_mip->w6);
|
|
m=nd;
|
|
if (mr_mip->apbase==64)
|
|
{ /* add leading zeros to base64 */
|
|
while (m%4!=0) m++;
|
|
}
|
|
if (rp>m) m=rp;
|
|
for (i=m;i>0;i--)
|
|
{
|
|
if (!mr_mip->fout && string==mr_mip->IOBUFF && n>=mr_mip->IOBSIZ-5)
|
|
{
|
|
mr_berror(_MIPP_ MR_ERR_IO_OVERFLOW);
|
|
MR_OUT
|
|
return n;
|
|
}
|
|
#ifdef MR_FLASH
|
|
if (i==rp && mr_mip->apbase<=60)
|
|
{
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]='.';
|
|
else fputc('.',mr_mip->otfile);
|
|
#else
|
|
string[n]='.';
|
|
#endif
|
|
n++;
|
|
}
|
|
#endif
|
|
if (i>nd && mr_mip->apbase!=64) ch='0';
|
|
else
|
|
{
|
|
ch=getdig(_MIPP_ mr_mip->w6,i);
|
|
check=mr_mip->check;
|
|
mr_mip->check=OFF;
|
|
putdig(_MIPP_ 0,mr_mip->w6,i);
|
|
/* mr_mip->check=mr_mip->check; Nasty stupid bug! */
|
|
mr_mip->check=check;
|
|
if (mr_mip->apbase<=60)
|
|
{ /* convert number to character */
|
|
ch+=48;
|
|
if (ch>=58) ch+=7;
|
|
if (ch>=91) ch+=6;
|
|
}
|
|
if (mr_mip->apbase==64)
|
|
{
|
|
if (ch<26) ch+=65;
|
|
if (ch>=26 && ch<52) ch+=71;
|
|
if (ch>=52 && ch<62) ch-=4;
|
|
if (ch==62) ch='+';
|
|
if (ch==63) ch='/';
|
|
}
|
|
}
|
|
if (i<rp && mr_mip->apbase<=60 && ch=='0' && size(mr_mip->w6)==0) break;
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]=MR_TOBYTE(ch);
|
|
else fputc(MR_TOBYTE(ch),mr_mip->otfile);
|
|
#else
|
|
string[n]=MR_TOBYTE(ch);
|
|
#endif
|
|
n++;
|
|
}
|
|
if (done) break;
|
|
#ifdef MR_FLASH
|
|
if (mr_mip->RPOINT) break;
|
|
denom(_MIPP_ x,mr_mip->w6);
|
|
if (size(mr_mip->w6)==1) break;
|
|
if (mr_mip->apbase<=60)
|
|
{
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]='/';
|
|
else fputc('/',mr_mip->otfile);
|
|
#else
|
|
string[n]='/';
|
|
#endif
|
|
n++;
|
|
}
|
|
done=TRUE;
|
|
#endif
|
|
}
|
|
/*
|
|
if (mr_mip->apbase==64)
|
|
{
|
|
while (n%3!=0)
|
|
{
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]='=';
|
|
else fputc('=',mr_mip->otfile);
|
|
#else
|
|
string[n]='=';
|
|
#endif
|
|
n++;
|
|
}
|
|
|
|
}
|
|
*/
|
|
/* Append a trailing 0 - it may be printable ascii text */
|
|
|
|
#ifndef MR_NO_FILE_IO
|
|
if (!mr_mip->fout) string[n]='\0';
|
|
else if (mr_mip->apbase<=60 || mr_mip->apbase==64) fputc('\n',mr_mip->otfile);
|
|
#else
|
|
string[n]='\0';
|
|
#endif
|
|
insign(s,x);
|
|
MR_OUT
|
|
return n;
|
|
}
|
|
|
|
#ifndef MR_NO_FILE_IO
|
|
|
|
int innum(_MIPD_ flash x,FILE *filep)
|
|
{ /* convert from string to flash x */
|
|
int n;
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return 0;
|
|
|
|
MR_IN(1)
|
|
|
|
mr_mip->infile=filep;
|
|
mr_mip->fin=TRUE;
|
|
n=instr(_MIPP_ x,NULL);
|
|
mr_mip->fin=FALSE;
|
|
|
|
MR_OUT
|
|
return n;
|
|
}
|
|
|
|
int otnum(_MIPD_ flash x,FILE *filep)
|
|
{ /* convert flash to string */
|
|
int n;
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return 0;
|
|
|
|
MR_IN(2)
|
|
|
|
mr_mip->otfile=filep;
|
|
mr_mip->fout=TRUE;
|
|
n=otstr(_MIPP_ x,NULL);
|
|
mr_mip->fout=FALSE;
|
|
|
|
MR_OUT
|
|
return n;
|
|
}
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#ifndef MR_FLASH
|
|
#ifndef MR_NO_STANDARD_IO
|
|
#ifndef MR_FP
|
|
|
|
int otnum(_MIPD_ flash x,FILE *filep)
|
|
{ /* support crude hex output only */
|
|
int i,j,ch,n;
|
|
BOOL leading=TRUE;
|
|
mr_small w;
|
|
n=0;
|
|
if (size(x)<0) fputc('-',filep);
|
|
for (i=(x->len&MR_OBITS)-1;i>=0;i--)
|
|
{
|
|
w=x->w[i];
|
|
for (j=MIRACL-4;j>=0;j-=4)
|
|
{
|
|
ch=48+((w>>j)&0xF);
|
|
if (ch==48 && leading) continue;
|
|
leading=FALSE;
|
|
if (ch>=58) ch+=7;
|
|
fputc(MR_TOBYTE(ch),filep);
|
|
n++;
|
|
}
|
|
}
|
|
fputc('\n',filep);
|
|
return n;
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|