Files
Hellfire/CODEC.CPP
T
Justin Marshall 101266ab72 Initial commit.
2026-04-27 10:35:40 -07:00

318 lines
8.1 KiB
C++

//******************************************************************
// codec.cpp
//******************************************************************
#include "diablo.h"
#pragma hdrstop
#include "engine.h"
//******************************************************************
// externs
//******************************************************************
void DesDestroy ();
void DesEncrypt (int, const void *, void *);
void DesInitialize (int, BOOL, const void *);
void IdeaDestroy ();
void IdeaEncrypt (int, const void *, void *);
void IdeaInitialize (int, BOOL, const void *);
void ShaDestroy ();
void ShaGetLastHash (int, void *);
void ShaHash (int, const void *, void *);
void ShaInitialize (int);
//******************************************************************
// set encryption methods
//******************************************************************
#define IDEA 0
#define DES 0
//******************************************************************
// private
//******************************************************************
#define BLOCKSIZE 64
#define VERSION 0
typedef struct _appendrec {
DWORD checkvalue;
BYTE version;
BYTE lastblocksize;
WORD reserved;
} appendrec, *appendptr;
typedef struct _keyrec {
WORD ideakey[3][8];
BYTE deskey[3][8];
BYTE shainitvect[64];
} keyrec, *keyptr;
//******************************************************************
//******************************************************************
static void DestroyKeys () {
#if DES
DesDestroy();
#endif
#if IDEA
IdeaDestroy();
#endif
ShaDestroy();
}
//******************************************************************
//******************************************************************
static void InitializeKeys (BOOL encrypt, const char *password) {
keyrec keyset;
// generate a key
srand(SAVE_GAME_KEY);
BYTE * pb = (BYTE *) &keyset;
for (int i = sizeof(keyset); i--; )
*pb++ = (BYTE) rand();
// HASH THE PASSWORD AND MIX IT WITH THE KEY
{
BYTE originalpassword[64];
BYTE hashedpassword[20];
{
int passchar = 0;
for (int loop = 0; loop < 64; ++loop) {
if (!*(password+passchar))
passchar = 0;
originalpassword[loop] = *(password+passchar++);
}
}
ShaInitialize(0);
ShaHash(0,originalpassword,hashedpassword);
ShaDestroy();
{
LPBYTE keysptr = (LPBYTE)&keyset;
for (int loop = 0; loop < sizeof(keyset); ++loop)
*(keysptr+loop) ^= hashedpassword[loop % 20];
}
ZeroMemory(originalpassword, sizeof originalpassword);
ZeroMemory(hashedpassword, sizeof hashedpassword);
}
// INITIALIZE THE ENCRYPTION ALGORITHMS
for (int loop = 0; loop < 3; ++loop) {
#if DES
DesInitialize(loop,encrypt,keyset.deskey[loop]);
#endif
#if IDEA
IdeaInitialize(loop,encrypt,keyset.ideakey[loop]);
#endif
ShaInitialize(loop);
ShaHash(loop,keyset.shainitvect,NULL);
}
// WIPE OUT THE LOCAL COPY OF THE KEYS
ZeroMemory(&keyset,sizeof(keyrec));
}
//******************************************************************
//******************************************************************
DWORD DecodeFile(BYTE * pbSrcDst,DWORD dwDstBytes,const char * pszPassword) {
app_assert(pbSrcDst);
app_assert(pszPassword);
// initialize encryption keys
InitializeKeys(0,pszPassword);
// make sure the length is correct
if (dwDstBytes <= sizeof(appendrec)) return 0;
dwDstBytes -= sizeof(appendrec);
if (dwDstBytes & (BLOCKSIZE-1)) return 0;
DWORD dwBytesLeft = dwDstBytes;
// DECRYPT THE FILE BLOCK BY BLOCK
BYTE buffer[2][BLOCKSIZE];
while (dwBytesLeft) {
// get the next chunk
CopyMemory(&buffer[0][0],pbSrcDst,BLOCKSIZE);
// DECRYPT THE BLOCK
{
BYTE hash[20];
ShaGetLastHash(0,hash);
int loop;
#if IDEA
for (loop = 0; loop < BLOCKSIZE; loop += 8) {
IdeaEncrypt(2,&buffer[0][loop],&buffer[1][loop]);
IdeaEncrypt(1,&buffer[1][loop],&buffer[0][loop]);
IdeaEncrypt(0,&buffer[0][loop],&buffer[1][loop]);
}
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[0][loop] = buffer[1][loop]-hash[(BLOCKSIZE-(loop+1)) % 20];
#endif
#if DES
for (loop = 0; loop < BLOCKSIZE; loop += 8) {
DesEncrypt(2,&buffer[0][loop],&buffer[1][loop]);
DesEncrypt(1,&buffer[1][loop],&buffer[0][loop]);
DesEncrypt(0,&buffer[0][loop],&buffer[1][loop]);
}
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[0][loop] = hash[loop % 20] ^ buffer[1][loop];
#endif
#if ! DES && ! IDEA
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[0][loop] = hash[loop % 20] ^ buffer[0][loop];
#endif
ShaHash(0,buffer[0],NULL);
ZeroMemory(hash,sizeof(hash));
}
// WRITE THE BLOCK
CopyMemory(pbSrcDst,&buffer[0][0],BLOCKSIZE);
// next block
pbSrcDst += BLOCKSIZE;
dwBytesLeft -= BLOCKSIZE;
}
// hide buffer contents
ZeroMemory(buffer,sizeof(buffer));
// CHECK THE FILE TERMINATION RECORD
const appendrec * append = (const appendrec *) pbSrcDst;
// CHECK THE ENCRYPTION VERSION
if (append->version > VERSION)
goto error;
// CONFIRM THAT THE KEY AND PASSWORD WERE VALID
{
BYTE hash[20];
ShaGetLastHash(0,hash);
if (append->checkvalue != * (LPDWORD) &hash[0]) {
ZeroMemory(hash,20);
goto error;
}
}
// SET THE EXACT OUTPUT SIZE
dwDstBytes -= BLOCKSIZE - append->lastblocksize;
DestroyKeys();
return dwDstBytes;
error:
DestroyKeys();
return 0;
}
//******************************************************************
// CalcEncodeDstBytes()
// -- calculate the number of bytes required to hold the encoded
// file information including the append record
//******************************************************************
DWORD CalcEncodeDstBytes(DWORD dwSrcBytes) {
app_assert(dwSrcBytes);
if (dwSrcBytes & (BLOCKSIZE-1))
dwSrcBytes += BLOCKSIZE - (dwSrcBytes & (BLOCKSIZE-1));
dwSrcBytes += sizeof(appendrec);
return dwSrcBytes;
}
//******************************************************************
//******************************************************************
void EncodeFile(BYTE * pbSrcDst,DWORD dwSrcBytes,DWORD dwDstBytes,const char * pszPassword) {
app_assert(pbSrcDst);
app_assert(pszPassword);
// make sure the user allocated enough bytes for the destination
if (dwDstBytes != CalcEncodeDstBytes(dwSrcBytes))
app_fatal("Invalid encode parameters");
// initialize encryption keys
InitializeKeys(1,pszPassword);
// ENCRYPT THE FILE BLOCK BY BLOCK
DWORD lastblocksize = 0;
BYTE buffer[2][BLOCKSIZE];
while (dwSrcBytes) {
// get the next src data chunk
DWORD blocksize = min(dwSrcBytes,BLOCKSIZE);
CopyMemory(&buffer[0][0],pbSrcDst,blocksize);
// blank out any unused portion of the buffer
if (blocksize < BLOCKSIZE)
ZeroMemory(&buffer[0][blocksize],BLOCKSIZE - blocksize);
// ENCRYPT THE BLOCK
{
BYTE hash[20];
ShaGetLastHash(0,hash);
ShaHash(0,buffer[0],NULL);
int loop;
#if ! DES && ! IDEA
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[0][loop] = hash[loop % 20] ^ buffer[0][loop];
#endif
#if DES
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[1][loop] = hash[loop % 20] ^ buffer[0][loop];
for (loop = 0; loop < BLOCKSIZE; loop += 8) {
DesEncrypt(0,&buffer[1][loop],&buffer[0][loop]);
DesEncrypt(1,&buffer[0][loop],&buffer[1][loop]);
DesEncrypt(2,&buffer[1][loop],&buffer[0][loop]);
}
#endif
#if IDEA
for (loop = 0; loop < BLOCKSIZE; loop++)
buffer[1][loop] = buffer[0][loop]+hash[(BLOCKSIZE-(loop+1)) % 20];
for (loop = 0; loop < BLOCKSIZE; loop += 8) {
IdeaEncrypt(0,&buffer[1][loop],&buffer[0][loop]);
IdeaEncrypt(1,&buffer[0][loop],&buffer[1][loop]);
IdeaEncrypt(2,&buffer[1][loop],&buffer[0][loop]);
}
#endif
// hide hash info
ZeroMemory(hash,sizeof(hash));
}
// write encrypted chunk to destination
CopyMemory(pbSrcDst,&buffer[0][0],BLOCKSIZE);
// next block
pbSrcDst += BLOCKSIZE;
dwSrcBytes -= blocksize;
lastblocksize = blocksize;
}
// hide buffer
ZeroMemory(buffer,sizeof(buffer));
// APPEND THE TERMINATION RECORD
BYTE hash[20];
appendrec * append = (appendrec *) pbSrcDst;
ShaGetLastHash(0,hash);
append->checkvalue = * (LPDWORD) &hash[0];
append->version = VERSION;
append->lastblocksize = (BYTE) lastblocksize;
append->reserved = 0;
DestroyKeys();
}