//
// File: cipher.cpp
// Sylvain Huet
// Created: 03/07/2001
//

//
// Modifications History
//
//$ LB (03/06/2002) : uncipher function : introduce specific key for clubhouse server
//



#include "include/vscol.h"


// fonction basique lisant un entier à partir de 4 octets (indépendant de little ou big endian)
int getint(char *buf)
{
	return (buf[0]&255)+((buf[1]&255)<<8)+((buf[2]&255)<<16)+((buf[3]&255)<<24);
}

// fonction basique écrivant un entier à partir de 4 octets (indépendant de little ou big endian)
int storeint(char *buf,int x)
{
	buf[0]=x;
	x>>=8;
	buf[1]=x;
	x>>=8;
	buf[2]=x;
	x>>=8;
	buf[3]=x;
	return 0;
}

void decipher(int v0,int v1,int *k, int *w0, int *w1)
{
   int y=v0,z=v1,sum=0xC6EF3720,delta=0x9E3779B9,n=32;

   /* sum = delta<<5, in general sum = delta * n */

   while(n-->0)
      {
		z-= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 & 3];
      sum -= delta;
		y-= (z<<4 ^ z>>5) + z ^ sum + k[sum&3];
      }
   
	*w0=y; *w1=z;
}

// decodage d'un fichier
int uncipher(char *buf,int size)
{
	int l;
	int i;
	int k[4];
	int v0,v1,w0,w1;



	int header=4;

	l=size-header;

	buf[0]=buf[1]=buf[2]=buf[3]=' ';	// on écrase le header par des espaces

	buf+=4;

//$ LB (03/06/2002) : specific key for clubhouse server
#ifdef CLUBHOUSE_SERVER

	k[0]=0xF067;	// initialisation de la clef
	k[1]=0xE189;
	k[2]=0xD245;
	k[3]=0xCB63;

#else

	k[0]=0x1234;	// initialisation de la clef
	k[1]=0x5678;
	k[2]=0x9abc;
	k[3]=0xdef0;

#endif

	for(i=0;i<l;i+=8)
	{
		v0=getint(buf);		// lecture de la source (64 bits)
		v1=getint(buf+4);
		decipher(v0,v1,k,&w0,&w1);	// decryptage
		storeint(buf,w0);	// écriture du résultat
		storeint(buf+4,w1);
		k[0]=w0;	// mise à jour de la moitié de la clef avec la valeur après décryptage
		k[1]=w1;
		buf+=8;
	}


	return 0;
}

