/***************************************************************************
*
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 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;iINPLEN;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