#include "comcryptPriv.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef macintosh
#include <MacMemory.h>
#endif
comMallocExternFcn *comMallocExt = NULL;
comFreeExternFcn *comFreeExt = NULL;
#if COM_STATS
comStats _comStats;
void resetComStats()
{
memset(&_comStats, 0, sizeof(comStats));
}
void getComStats(comStats *stats)
{
*stats = _comStats;
}
#else
#define incrComStat(stat, num)
#endif
void key_perm(
const unsigned char *key,
int keybytes,
unsigned char *map,
unsigned char *invmap)
{
int i, j, tmp, sum;
for(sum = 0, j = 0; j < keybytes; j++) {
sum += key[j];
}
for(j=0; j < 256; j++) {
map[j] = j;
}
for(j=0; j < 255; j++) {
i = (key[j % keybytes] + j*sum) & 0xff;
tmp = map[i];
map[i] = map[j];
map[j] = tmp;
}
for(j=0; j<256; j++) {
invmap[map[j]] = j;
}
}
int keybyte(
const unsigned char *key,
int keybytes,
int index)
{
return((int) key[index % keybytes]);
}
int keynybble(
const unsigned char *key,
int keybytes,
int index)
{
int i = index % (2*keybytes);
int j;
j = key[i>>1];
if(i & 1) j >>= 4;
return(j & 0xf);
}
#define HASH_SEED 3
#define HASH_REDUCE 1023
static unsigned keyHash(const unsigned char *key, unsigned keylen)
{
unsigned x = HASH_SEED;
unsigned ctr;
for(ctr=0; ctr<keylen; ctr++) {
x = (x * (key[ctr] + (ctr & HASH_REDUCE) + 1)) % HASH_PRIME;
}
return x;
}
void mallocCodeBufs(comcryptBuf *cbuf)
{
cbuf->codeBufSize = comcryptMaxOutBufSize(NULL,
CC_BLOCK_SIZE,
CCOP_COMCRYPT,
1);
cbuf->codeBuf = (unsigned char *)ascMalloc(cbuf->codeBufSize);
cbuf->level2BufSize = comcryptMaxOutBufSize(NULL,
MAX_TOKENS, CCOP_COMCRYPT,
1);
cbuf->level2Buf = (unsigned char *)ascMalloc(cbuf->level2BufSize);
cbuf->queue = (queueElt *)ascMalloc(sizeof(queueElt) * QLEN);
#if QUEUE_LOOKAHEAD
cbuf->lookAhead = (unsigned char *)ascMalloc(LOOKAHEAD_SIZE);
#else
cbuf->lookAhead = NULL;
#endif
cbuf->sigArray = (unsigned *)ascMalloc((MAX_TOKENS + 1) * sizeof(unsigned));
}
void initCodeBufs(
comcryptBuf *cbuf,
const unsigned char *key,
unsigned keyLen,
unsigned char laEnable,
unsigned char sigSeqEnable)
{
unsigned ct;
unsigned qval;
unsigned char khash = (unsigned char)keyHash(key, keyLen);
cbuf->nybbleDex = khash;
if(laEnable) {
memset(cbuf->lookAhead, 0, LOOKAHEAD_SIZE);
}
laprintf(("initing queue and lookahead\n"));
for(ct=0; ct<QLEN; ct++) {
unsigned short sbyte = ct ^ khash;
qval = (sbyte << 8) | ct;
cbuf->queue[ct] = qval;
if(laEnable) {
markInQueue(cbuf, qval, 1);
}
}
cbuf->f1 = F1_DEFAULT;
cbuf->f2 = F2_DEFAULT;
cbuf->jmatchThresh = THRESH_2LEVEL_JMATCH_DEF;
cbuf->minByteCode = THRESH_2LEVEL_NUMBYTECODES_DEF;
if(sigSeqEnable) {
initSigSequence(cbuf, key, keyLen);
}
}
void freeCodeBufs(comcryptBuf *cbuf)
{
if(cbuf->queue != NULL) {
ascFree(cbuf->queue);
}
if(cbuf->codeBuf != NULL) {
ascFree(cbuf->codeBuf);
}
if(cbuf->level2Buf != NULL) {
ascFree(cbuf->level2Buf);
}
if(cbuf->nextBuf != NULL) {
freeCodeBufs(cbuf->nextBuf);
ascFree(cbuf->nextBuf);
cbuf->nextBuf = NULL;
}
if(cbuf->lookAhead != NULL) {
ascFree(cbuf->lookAhead);
}
if(cbuf->sigArray != NULL) {
ascFree(cbuf->sigArray);
}
}
void serializeInt(
unsigned i,
unsigned char *buf)
{
buf[0] = (unsigned char)(i >> 24);
buf[1] = (unsigned char)(i >> 16);
buf[2] = (unsigned char)(i >> 8);
buf[3] = (unsigned char)(i & 0xff);
}
unsigned deserializeInt(unsigned char *buf)
{
unsigned i;
i = ((unsigned)buf[0]) << 24;
i |= ((unsigned)buf[1]) << 16;
i |= ((unsigned)buf[2]) << 8;
i |= buf[3];
return i;
}
#if COM_PARAM_ENABLE
unsigned getF1(comcryptObj cobj)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
return cpriv->cbuf.f1;
}
void setF1(comcryptObj cobj, unsigned f1)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
cpriv->cbuf.f1 = f1;
if(cpriv->cbuf.nextBuf != NULL) {
cpriv->cbuf.nextBuf->f1 = f1;
}
}
unsigned getF2(comcryptObj cobj)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
return cpriv->cbuf.f2;
}
void setF2(comcryptObj cobj, unsigned f2)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
cpriv->cbuf.f2 = f2;
if(cpriv->cbuf.nextBuf != NULL) {
cpriv->cbuf.nextBuf->f2 = f2;
}
}
unsigned getJmatchThresh(comcryptObj cobj)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
return cpriv->cbuf.jmatchThresh;
}
void setJmatchThresh(comcryptObj cobj, unsigned jmatchThresh)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
cpriv->cbuf.jmatchThresh = jmatchThresh;
if(cpriv->cbuf.nextBuf != NULL) {
cpriv->cbuf.nextBuf->jmatchThresh = jmatchThresh;
}
}
unsigned getMinByteCode(comcryptObj cobj)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
return cpriv->cbuf.minByteCode;
}
void setMinByteCode(comcryptObj cobj, unsigned minByteCode)
{
comcryptPriv *cpriv = (comcryptPriv *)cobj;
cpriv->cbuf.minByteCode = minByteCode;
if(cpriv->cbuf.nextBuf != NULL) {
cpriv->cbuf.nextBuf->minByteCode = minByteCode;
}
}
#endif
#if COM_LA_DEBUG
int testLookAhead(comcryptBuf *cbuf, int i1, int i2)
{
unsigned i;
if(!cbuf->laEnable) {
return 0;
}
for(i=0; i<QLEN; i++) {
if(!inQueue(cbuf, cbuf->queue[i])) {
printf("aaagh, corrupted lookahead - in queue[], !inQueue()\n");
printf("i=0x%x i1=0x%x i2=0x%x\n",
i, i1, i2);
printf("\n");
exit(1);
}
}
return 0;
}
int initTestLookAhead(comcryptBuf *cbuf)
{
#if QUEUE_LOOKAHEAD_BIT
unsigned codeWord = 0;
unsigned char bit;
unsigned short byte;
unsigned char *la = cbuf->lookAhead;
for(byte=0; byte<LOOKAHEAD_SIZE; byte++) {
for(bit=1; bit!=0; bit<<=1) {
if(la[byte] & bit) {
int i;
int found = 0;
for(i=0; i<QLEN; i++) {
if(cbuf->queue[i] == codeWord) {
found = 1;
break;
}
}
if(!found) {
printf("***corrupted init lookahead - in l.a., "
"not in queue[]\n");
printf("codeWord 0x%x\n", codeWord);
printf("\n");
exit(1);
}
}
codeWord++;
}
}
#endif
return 0;
}
#endif
void initSigSequence(comcryptBuf *cbuf,
const unsigned char *key,
unsigned keyLen)
{
unsigned seed = IN_OFFSET;
unsigned j;
for(j=0; j<keyLen; j++) {
seed += key[j];
}
seed %= HASH_PRIME;
if(seed == 0) {
seed = IN_OFFSET;
}
cbuf->sigArray[0] = (unsigned short)seed;
}
#if 0
void nextSigWord(comcryptBuf *cbuf,
unsigned sigDex, unsigned match,
unsigned above) {
unsigned offset;
unsigned short *sigArray = cbuf->sigArray;
#if COM_DEBUG
if(sigDex == 0) {
printf("nextSigWord underflow\n");
exit(1);
}
if(sigDex > MAX_TOKENS) {
printf("nextSigWord overflow\n");
exit(1);
}
#endif
if(match) {
offset = IN_OFFSET;
}
else {
offset = OUT_OFFSET;
}
#if 1
sigArray[sigDex] = (sigArray[sigDex-1] * (above + offset)) % HASH_PRIME;
#endif
}
#endif
void sigMunge(comcryptBuf *cbuf,
const unsigned char *tokenPtr,
unsigned numTokens,
unsigned char *byteCodePtr,
unsigned char *longCodePtr)
{
unsigned char tokenBit = 0x01;
unsigned token;
unsigned short sig;
for(token=0; token<numTokens; token++) {
sig = cbuf->sigArray[token];
if(*tokenPtr & tokenBit) {
*longCodePtr++ ^= (unsigned char)(sig >> 8);
*longCodePtr++ ^= (unsigned char)sig;
}
else {
*byteCodePtr++ ^= (unsigned char)sig;
}
tokenBit <<= 1;
if(tokenBit == 0) {
tokenBit = 0x01;
tokenPtr++;
}
}
}
void *ascMalloc(unsigned size)
{
#ifdef macintosh
Handle h;
OSErr err;
Ptr p;
#endif
if(comMallocExt != NULL) {
return (comMallocExt)(size);
}
#ifdef macintosh
h = nil;
err = noErr;
h = NewHandleSys(size); do{
HLockHi(h); err = MemError();
if( err != noErr ) break;
p = *h;
}while(0);
if( err != noErr ){
return NULL;
}
return p;
#else
return malloc(size);
#endif
}
void ascFree(void *data)
{
#ifdef macintosh
Handle h;
#endif
if(comFreeExt != NULL) {
(comFreeExt)(data);
return;
}
#ifdef macintosh
if( data != nil ){
h = RecoverHandle((Ptr) data);
DisposeHandle(h);
}
#else
free(data);
#endif
}