#include "fullSpec.h"
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <dir.h>

#define IGNORE 0
#define RETRY  1
#define ABORT  2
#define BREAK  3
#define PlainDataLen   32000/*24000*/
#define CipherDataLen  32000/*24000*/

int handler(int errval,int ax,int bp,int si);

/*
#define TRACE_DEF
*/
#ifdef TRACE_DEF
FILE *fu_trace;
#endif /* TRACE_DEF*/
ErreurDoNotExit(char *);

char Minicodage[] = "4630";
unsigned long decryptedLen;
unsigned long cipherDataLen,plainDataLen;
BYTE *point;
BYTE destine[60],destineori[60],floppy[60],floppyori[60], errmsg[100];
BYTE source[60],sourceori[60];
BYTE wrkspc[60];
BYTE fullPassword[fullPasswordLength + 1];
BYTE be_filename[5]; /* be.1 - be.2 - be.3 */

int ret/*,count*/,x,j;             /* holds the return code of important method calls. */
unsigned int count;
unsigned long matches;        /* counts the number of equal bytes in the plaintext and the de ed ciphertext. */
unsigned long i;              /* counter to produce nice output */
keyInstance encKeyInst;       /* state of the encryption engine */
cipherInstance encCipherInst; /* specifies the encryption mode */
keyInstance decKeyInst;       /* state of the decryption engine */
cipherInstance decCipherInst; /* specifies the decryption mode */

BYTE cipherKey[100];
BYTE macKey[100];

BYTE encKey[100];
BYTE iv[100];
BYTE derivedKey[100];
BYTE decryptedMacKey[100];
BYTE decryptedEncKey[100];
BYTE *decrypted = NULL;
BYTE hashResult[100];
BYTE macResult[100];
BYTE *authenticatedEncryptedPlaintext;
BYTE dataForFloppy[50];
BYTE dataFromFloppy[50];
BYTE mode[2];
BYTE niveau[2];

int hashResultLen = sizeof (hashResult);
int dataForFloppyLength;

#include "alg-fst.c"
#include "api-fst.c"
#include "encdec.c"
#include "enckeys.c"
#include "encmac.c"
#include "hashcomp.c"
#include "maccomp.c"
#include "psswd.c"

/****************************/
main(int argc, char *argv[])
/****************************/
{
  FILE *fu;

  point = errmsg;

  strcpy(mode,argv[1]);
  strcpy(niveau,argv[2]);
  strcpy(fullPassword,argv[3]);
  strcpy(sourceori,argv[4]);
  strcpy(destineori,argv[5]);
  strcpy(floppyori,argv[6]);

  strcpy(destine,destineori);
  strcat(destine,"\\LOG.ERR");
  unlink(destine);

#ifdef TRACE_DEF
  fu_trace = fopen("C:\\lv2006\\arijn\\TRACE.LOG","w");
#endif /* TRACE_DEF */

  /* If aborded (diskette removed) -> \\LOG.ERR
  if((mode[0] == 'r') ||  (mode[0] == 'R'))
  {
    if(strcmp(niveau,"1") == 0)
    { */
      ErreurDoNotExit("arijn");
    /*}
  } */

  /* be_filename */
  strcpy(be_filename, "be.");
  strcat(be_filename, niveau);
  be_filename[4] = 0x00;

/* <validatePassword> determines whether an integrity-protected password is valid. */
/* <return code>      zero refers to a valid password, other values refer to an invalid password. */
/* <fullPassword>     refers to the zero-terminated string with the integrity-protected password of <fullPassword-1> characters. */



  ret = validatePassword (fullPassword);
  if (ret != 0)
    {
	  sprintf(errmsg,"password <%s> is *INVALID*\n", fullPassword);
	  Erreur(point);
    }

/* <computeKeyFromPassword> computes a the hash value using the zero-terminated integrity-protected <fullPassword>. */
/*                          this method validates the integrity-protected fullPassword before computing the cipherKey. */
/* <return code>            zero means ok, all other values refer to an error. */
/* <cipherKey>                    refers to the array of byte that must be able to accomodate 16 bytes. */
/* <fullPassword>           refers to the zero-terminated integrity-protected fullPassword. */

  ret = computeKeyFromPassword (derivedKey, fullPassword);
  if (ret != 0)
    {
       sprintf(errmsg,"cipherKey derivation fails with error <%i>\n",ret);
       Erreur(point);
    }

/* <encryptKeys> produces the ciphertext of a <macKey> and an <encKey>, given an initialization vector <iv> and the 16-byte key with which these keys must be encrypted. */
/* <return code> an integer, negative values refer to an error code, positive values specify the length of the output parameter <dataForFloppy>. */
/* <dataForFloppy> refers to an array of char that will contain the information that can be stored on a floppy disk. */
/*                 <dataForFloppy> must be able to accomodate at least <3*<blockLength>> bytes. */
/* <cipherKey>     refers to the 16-byte encryption key with which the two keys (<macKey> and <encKey>) must be encrypted. */
/*                 this key must be different must not be related to <encKey> and <macKey> */
/* <iv>            refers to the 16-byte initialization vector for the encryption. */
/*                 <iv> must be used only once, and should be generated randomly. */
/* <macKey>        refers to the 16-byte MAC-key that must be encrypted. */
/* <encKey>        refers to the 16-byte encryption key that must be encrypted. */

  if((mode[0] == 'w') ||  (mode[0] == 'W'))
    {
         strcpy(floppy,floppyori);
         strcat(floppy,"\\");
         strcat(floppy,"ivmac.be");
         Rfile(floppy);

         for (i = 0; i < 16;i++)
            iv[i] = wrkspc[i];
         iv[i] = 0x00;


         makeKeyBinary (&encKeyInst, DIR_ENCRYPT, derivedKey);
         cipherInitBinary (&encCipherInst, iv);

         Rfloppy(dataFromFloppy);
         ret= decryptKeys (decryptedMacKey, decryptedEncKey, dataFromFloppy, derivedKey);
	 if (ret < 0)
	    {
	       sprintf(errmsg,"problem during decryptKeys: <%i>.\n", ret);
	       Erreur(point);
	    }

          makeKeyBinary (&encKeyInst, DIR_ENCRYPT, decryptedEncKey);
          cipherInitBinary (&encCipherInst, iv);

          CalculMac(destineori);
          Wmac();
    }

/* <decryptKeys> decrypts the data retrieved from floppy <dataFromFloppy>. */
/* <return code> an integer, negative values refer to an error code, zero means that no problem was detected.. */
/*               note that zero does not indicate that the decrypted keys are valid: no redundancy is added to avoid exhaustive key searches. */
/* <macKey>      refers to the 16-byte MAC-key that has been decrypted. */
/* <encKey>      refers to the 16-byte encryption key that has been decrypted. */
/* <dataFromFloppy> refers to an array of char that contains the information that was stored on a floppy disk. */
/*                 <dataFromFloppy> must consist of <3*<blockLength>> bytes. */
/* <cipherKey>     refers to the 16-byte encryption key with which the <dataFromFloppy> will be decrypted. */

  else
   {
          strcpy(source,sourceori);
          strcat(source,"\\");
          strcat(source,be_filename);
          Rfile(source);

         for (i = 0; i < 16;i++)
            iv[i] = wrkspc[i];
         iv[i] = 0x00;

        if(strcmp(niveau,"3") == 0)
           {
            /* Nouveau IV */
            iv[0] = Minicodage[0];
            iv[2] = Minicodage[1];
            iv[4] = Minicodage[2];
            iv[6] = Minicodage[3];
           /***********************/
           }


         makeKeyBinary (&encKeyInst, DIR_DECRYPT, derivedKey);
         cipherInitBinary (&encCipherInst, iv);
         Rfloppy(dataFromFloppy);
         ret= decryptKeys (decryptedMacKey, decryptedEncKey, dataFromFloppy, derivedKey);
	 if (ret < 0)
	    {
	       sprintf(errmsg,"problem during decryptKeys: <%i>.\n", ret);
	       Erreur(point);
	    }

          makeKeyBinary (&decKeyInst, DIR_DECRYPT, decryptedEncKey);
          cipherInitBinary (&decCipherInst, iv);

          CalculMac(sourceori);

          strcpy(source,sourceori);
          strcat(source,"\\");
          strcat(source,be_filename);
          Rfile(source);

        for (i = 0; i < macResultLen;i++)
            if(macResult[i] != wrkspc[i+16])
	    {
               sprintf(errmsg,"problem CRC.\n");
	       Erreur(point);
	    }
    }

  /* If aborded (diskette removed) -> \\LOG.ERR
  if((mode[0] == 'r') ||  (mode[0] == 'R'))
  {
    if(strcmp(niveau,"1") == 0)
    { */
			strcpy(destine,destineori);
			strcat(destine,"\\LOG.ERR");
			unlink(destine);
    /*}
  }*/
#ifdef TRACE_DEF
  fclose(fu_trace);
#endif /* TRACE_DEF*/
}
/****************************************************************************/
/*             F I C H I E R     D E S    E R R E U R S                     */

ErreurDoNotExit(char *msg)
{
  FILE *fps;

  strcpy(destine,destineori);
  strcat(destine,"\\LOG.ERR");
  fps = fopen(destine,"a");
  fputs(msg,fps);
  fclose(fps);
}

Erreur(char *msg)
{
  FILE *fps;

  strcpy(destine,destineori);
  strcat(destine,"\\LOG.ERR");
  fps = fopen(destine,"a");
  fputs(msg,fps);
  fclose(fps);
  exit(0);
}

#ifdef TRACE_DEF
Trace(char *msg)
{
  fputs(msg,fu_trace);
}
#endif /* TRACE_DEF*/
/****************************************************************************/
/****************************************************************************/
/*                            F I C H I E R S                               */

Wfloppy(char *msg,int ret)
{
  int fd;

  strcpy(floppy,floppyori);
  strcat(floppy,"\\floppy.be");

  if((fd = open(floppy,O_CREAT | O_RDWR | O_BINARY,0x0100 | 0x0080)) == -1)
    {
	  sprintf(errmsg,"error opening Floppy.be");
	  Erreur(point);
    }

  write(fd,msg,ret);
  close(fd);
  exit(0);
}

/****************************************************************************/

Rfloppy(char *msg)
{
  int fd;

  strcpy(floppy,floppyori);
  strcat(floppy,"\\Floppy.be");

  if((fd = open( floppy, O_BINARY | O_RDWR)) == -1)
    {
	  sprintf(errmsg,"error opening Floppy.be");
	  Erreur(point);
    }
  read(fd,msg,80);
  close(fd);

}

/****************************************************************************/

Rfile(char *fichier)
{
  int fps;
  BYTE Bffer[100],C1,C2;
  int i,j,n,Carry;


  if((fps = open( fichier, O_RDWR | O_BINARY,0x0100 | 0x0080)) == -1)
    {
	  sprintf(errmsg,"error opening %s",fichier);
	  Erreur(point);
    }

  Carry = read(fps,Bffer,64);
  close(fps);
  Bffer[Carry] = 0x00;

  for ( i = 0 ; i <  Carry ; i++)
      {
	 if(Bffer[i] < 58)
	      Bffer[i] -= 48;
	  else
	      Bffer[i] -= 55;
      }


  for ( i = 0, j = 0; j < Carry / 2; j++)
      {
           wrkspc[j]   = Bffer[i++] << 4;
           wrkspc[j]   = Bffer[i++] | wrkspc[j];
      }
      wrkspc[j] = 0x00;
}

/*****************************************************************************/
Wmac()
{
  int fd;
  int i;
  BYTE Bffer[100];
  BYTE Cai[3];

  strcpy(destine,destineori);
  strcat(destine,be_filename);
  unlink(destine);
#ifdef TRACE_DEF
  Trace(destine);
  Trace("\n");
#endif /* TRACE_DEF*/
  if((fd = open(destine,O_CREAT | O_RDWR | O_BINARY,0x0100 | 0x0080)) == -1)
    {
	  sprintf(errmsg,"error opening mac.be");
	  Erreur(point);
    }

  Bffer[0] = 0x00;
  for(i = 0; i < 16;i++)
        {
          sprintf(Cai, "%02X",(unsigned char) iv[i]);
          strcat(Bffer,Cai);
        }

  for(i = 0; i < macResultLen;i++)
        {
          sprintf(Cai, "%02X",(unsigned char) macResult[i]);
          strcat(Bffer,Cai);
        }
  write(fd,Bffer,strlen(Bffer));
  close(fd);
}
/*****************************************************************************/
/*****************************************************************************/
error_win(int numerror)
{
 int retval;

 while(1)
   {
     switch(numerror)
	{
	  case 0 :
		   retval = RETRY;
		   break;
	  case 2 :
		   retval = RETRY;
		   break;
	  default: retval = BREAK;
	}
      return(retval);
   }
}
/****************************************************************************/
int handler(int errval,int ax,int bp,int si)
{
   unsigned di;
   int drive;
   int errorno;

   di= _DI;
   if (ax < 0)
       hardretn(ABORT);

/* erreur disquette */
   errorno = di & 0x00FF;
   hardresume(error_win(errorno));
   return ABORT;
}

unsigned long CalculNbFichier()
{
	struct ffblk fileinfo;
	unsigned long cpt;

	strcpy(source,sourceori);
	strcat(source,"\\*.*");
	if(findfirst(source,&fileinfo,0) == -1) return 0.;

	cpt = 1;
	while(findnext(&fileinfo) == 0)
	{
		if(strnicmp(fileinfo.ff_name,"BE",2) == 0
				|| strcmp(fileinfo.ff_name,"LOG.ERR")== 0)
			continue;
		++cpt;
	}

	return(cpt);
}

/****************************************************************************/
CalculMac(char *Path)
{
	register int n, i, Carry;
	struct ffblk fileinfo;
	int  handel_Read;
	BYTE plainData [PlainDataLen];
	BYTE cipherData[CipherDataLen];
	BYTE Buffer [1050];
#ifdef TRACE_DEF
	unsigned long nbtotfiles, counter;
#endif
	j = 0;
	plainData[j] = 0x00;

#ifdef TRACE_DEF
	nbtotfiles = CalculNbFichier();
	/*printf("%ld\n", nbtotfiles);*/
#endif

	strcpy(source,sourceori);
	strcat(source,"\\*.*");
	if(findfirst(source,&fileinfo,0) == -1)
	{
		sprintf(errmsg,"Aucun fichier … traiter\n");
		Erreur(point);
	}

#ifdef TRACE_DEF
	counter = 1.;
#endif
	while(1)
	{
		if(strnicmp(fileinfo.ff_name,"BE",2) == 0
				|| strcmp(fileinfo.ff_name,"LOG.ERR")== 0)
		{
			if(findnext(&fileinfo) != 0)
				break;
			continue;
		}
		/*
		strcpy(source,Path);
		strcat(source,"\\");
		/*printf("%d [%s]\n", x++, fileinfo.ff_name);
		strcat(source,fileinfo.ff_name);*/
		sprintf(source,"%s\\%s", Path,fileinfo.ff_name);

#ifdef TRACE_DEF
		sprintf(Buffer, "%ld (%ld) [%s]\n", counter++, nbtotfiles, fileinfo.ff_name);
		trace(Buffer);
#endif /* TRACE_DEF*/

		handel_Read = open(source, O_RDWR | O_BINARY,0x0100 | 0x0080);
		if(handel_Read == -1)
		{
			sprintf(errmsg,"Erreur d'ouverture du fichier %s\n",source);
			Erreur(point);
		}
		while((Carry = read(handel_Read,Buffer,1024)) != NULL)
		{
			if(j+macResultLen >= PlainDataLen)
			{
				computeMac (macResult, macResultLen, plainData, j, decryptedMacKey);
				j=0;
				for (i = 0; i < macResultLen;i++,j++)
					plainData[j] = macResult[i];
			}
			computeMac (macResult, macResultLen, Buffer, Carry, decryptedMacKey);
			for (i = 0; i < macResultLen;i++,j++)
				plainData[j] = macResult[i];
		}
		plainData[j] = 0x00;
		close(handel_Read);
		if(findnext(&fileinfo) != 0)
			break;
	}

	computeMac (macResult, macResultLen, plainData, j, decryptedMacKey);
}
