Files
maui/src/mcom/MSec.c
T
dev 9a0042c61e Initial revision
git-svn-id: svn://opensvn.adaptivecomputing.com/maui/trunk@2 3f5042e3-fb1d-0410-be18-d6ca2573e517
2005-07-12 21:12:53 +00:00

2013 lines
38 KiB
C

/* HEADER */
#include "moab.h"
#include "moab-proto.h"
extern mlog_t mlog;
extern msched_t MSched;
extern m64_t M64;
extern const char *MCSAlgoType[];
extern const char *MBool[];
/* DES config */
#define MAX_MDESCKSUM_ITERATION 4
unsigned short __MSecDoCRC(unsigned short,unsigned char);
int __MSecPSDES(unsigned int *,unsigned int *);
/* END DES config */
/* HMAC config */
#ifndef SHA_DIGESTSIZE
# define SHA_DIGESTSIZE 20
#endif
#ifndef SHA_BLOCKSIZE
# define SHA_BLOCKSIZE 64
#endif
typedef struct {
MUINT4 state[5];
MUINT4 count[2];
unsigned char buffer[64];
} SHA1_CTX;
typedef union
{
unsigned char c[64];
MUINT4 l[16];
} CHAR64LONG16;
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN)
# if defined(__BYTE_ORDER)
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define SHA1_LITTLE_ENDIAN 1
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
# define SHA1_BIG_ENDIAN 1
# endif
# endif
# if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN)
# if defined(__AIX43) || defined(__AIX51) || defined(__HPUX) || defined(__IRIX) || defined(__SOLARIS)
# define SHA1_BIG_ENDIAN
# else
# define SHA1_LITTLE_ENDIAN
# endif
# endif
#endif /* !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) */
#if defined(SHA1_LITTLE_ENDIAN) && defined(SHA1_BIG_ENDIAN)
#error "So, which is it: big endian or little endian?"
#endif
#if defined(SHA1_LITTLE_ENDIAN)
# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
# define SHA1_ENDIAN_KNOWN
#else
# define blk0(i) block->l[i]
# define SHA1_ENDIAN_KNOWN
#endif
#if !defined(SHA1_ENDIAN_KNOWN)
#error "ENDIANness of system not defined."
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
int MSecHMACGetDigest(unsigned char *,int,unsigned char *,int,char *,int,char *,mbool_t,mbool_t);
static void __MSecSHA1Transform(MUINT4 S[5],unsigned char B[64]);
void __MSecSHA1Init(SHA1_CTX *);
void __MSecSHA1Update(SHA1_CTX *,unsigned char *,MUINT4);
void __MSecSHA1Final(unsigned char D[20],SHA1_CTX *);
void __MSecHMACTruncate (char *,char *,int);
/* END HMAC config */
/* MD5 config */
#ifdef __MMD5
#include <openssl/md5.h>
#ifdef MD5_DIGEST_LENGTH
#define MMD5_DIGESTSIZE MD5_DIGEST_LENGTH
#else /* MD5_DIGEST_LENGTH */
#define MMD5_DIGESTSIZE 0
#endif /* MD5_DIGEST_LENGTH */
#else /* __MMD5 */
#define MMD5_DIGESTSIZE 0
#endif /* __MMD5 */
int MSecMD5GetDigest(char *,int,char *,int,char *,int);
/* END MD5 config */
#ifndef __M32COMPAT
int M64Init(
m64_t *M) /* I (modified) */
{
if (sizeof(int) == 4)
{
/* 32 bit operation */
M->Is64 = FALSE;
M->INTBC = M32INTBITS;
M->INTLBC = M32INTLBITS;
M->MIntSize = M32INTSIZE;
M->IntShift = M32INTSHIFT;
}
else
{
/* 64 bit operation */
M->Is64 = TRUE;
M->INTBC = M64INTBITS;
M->INTLBC = M64INTLBITS;
M->MIntSize = M64INTSIZE;
M->IntShift = M64INTSHIFT;
}
MDB(5,fSTRUCT) MLog("INFO: 64Bit enabled: %s UINT4[%d] UINT8[%d]\n",
MBool[M->Is64],
sizeof(MUINT4),
sizeof(MUINT8));
return(SUCCESS);
} /* END M64Init() */
#endif /* !__M32COMPAT */
int MSecGetChecksum(
char *Buf, /* I */
int BufSize, /* I */
char *Checksum, /* O */
char *Digest, /* O (optional) */
enum MChecksumAlgoEnum Algo, /* I */
char *CSKeyString) /* I */
{
#ifndef __MPROD
const char *FName = "MSecGetChecksum";
MDB(5,fSTRUCT) MLog("%s(Buf,%d,Checksum,%s,CSKey)\n",
FName,
BufSize,
MCSAlgoType[Algo]);
#endif /* !__MPROD */
if ((Buf == NULL) || (Checksum == NULL) || (CSKeyString == NULL))
{
return(FAILURE);
}
switch(Algo)
{
case mcsaHMAC:
{
MSecHMACGetDigest(
(unsigned char *)CSKeyString,
strlen(CSKeyString),
(unsigned char *)Buf,
strlen(Buf),
Checksum,
SHA_DIGESTSIZE,
NULL,
FALSE,
FALSE);
} /* END BLOCK */
break;
case mcsaHMAC64:
{
MSecHMACGetDigest(
(unsigned char *)CSKeyString,
strlen(CSKeyString),
(unsigned char *)Buf,
strlen(Buf),
Checksum,
SHA_DIGESTSIZE,
Digest,
TRUE,
TRUE);
} /* END BLOCK */
break;
case mcsaMD5:
{
MSecMD5GetDigest(
CSKeyString,
strlen(CSKeyString),
Buf,
strlen(Buf),
Checksum,
MMD5_DIGESTSIZE);
} /* END BLOCK */
break;
case mcsaRemote:
{
char CmdLine[MMAX_LINE];
sprintf(CmdLine,"mauth \"%s\"",
Buf);
#ifndef __M32COMPAT
if (MUReadPipe(CmdLine,NULL,Checksum,MMAX_LINE) == FAILURE)
{
return(FAILURE);
}
#endif /* __M32COMPAT */
} /* END BLOCK */
break;
case mcsaDES:
default:
{
unsigned int crc;
unsigned int lword;
unsigned int rword;
int index;
unsigned int SKey;
SKey = (unsigned int)strtoul(CSKeyString,NULL,0);
crc = 0;
for (index = 0;index < BufSize;index++)
{
crc = (unsigned int)__MSecDoCRC((unsigned short)crc,Buf[index]);
}
lword = crc;
rword = SKey;
__MSecPSDES(&lword,&rword);
Checksum[0] = '\0';
sprintf(Checksum,"%08x%08x",
(int)lword,
(int)rword);
} /* END BLOCK */
break;
} /* END switch(Algo) */
/* NOTE: enable logging only for unit testing. MUST DISABLE FOR PRODUCTION */
/*
MDB(8,fSTRUCT) MLog("INFO: checksum '%s' calculated for %d byte buffer '%s' using seed %x\n",
Checksum,
BufSize,
Buf,
SKey);
*/
return(SUCCESS);
} /* END MSecGetChecksum() */
int MSecGetChecksum2(
char *Buf1, /* I */
int BufSize1, /* I */
char *Buf2, /* I */
int BufSize2, /* I */
char *Checksum, /* O */
char *Digest, /* O (optional) */
enum MChecksumAlgoEnum Algo, /* I */
char *CSKeyString) /* I */
{
#ifndef __MPROD
const char *FName = "MSecGetChecksum2";
MDB(5,fSTRUCT) MLog("%s(Buf1,%d,Buf2,%d,Checksum,%s,CSKey)\n",
FName,
BufSize1,
BufSize2,
MCSAlgoType[Algo]);
#endif /* !__MPROD */
if ((Buf1 == NULL) || (Buf2 == NULL) || (Checksum == NULL))
{
return(FAILURE);
}
switch(Algo)
{
case mcsaHMAC:
{
char *ptr;
/* NOTE: merge header and data */
ptr = (char *)malloc(BufSize1 + BufSize2);
strcpy(ptr,Buf1);
strcpy(ptr + BufSize1,Buf2);
MSecHMACGetDigest(
(unsigned char *)CSKeyString,
strlen(CSKeyString),
(unsigned char *)ptr,
BufSize1 + BufSize2,
Checksum,
SHA_DIGESTSIZE,
NULL,
FALSE,
FALSE);
free(ptr);
} /* END BLOCK */
break;
case mcsaHMAC64:
{
char *ptr;
/* NOTE: merge header and data */
ptr = (char *)malloc(BufSize1 + BufSize2);
strcpy(ptr,Buf1);
strcpy(ptr + BufSize1,Buf2);
MSecHMACGetDigest(
(unsigned char *)CSKeyString,
strlen(CSKeyString),
(unsigned char *)ptr,
strlen(ptr),
Checksum,
SHA_DIGESTSIZE,
Digest,
TRUE,
TRUE);
free(ptr);
} /* END BLOCK */
break;
case mcsaMD5:
{
char *ptr;
/* NOTE: merge header and data */
ptr = (char *)malloc(BufSize1 + BufSize2);
strcpy(ptr,Buf1);
strcpy(ptr + BufSize1,Buf2);
MSecMD5GetDigest(
CSKeyString,
strlen(CSKeyString),
ptr,
BufSize1 + BufSize2,
Checksum,
MMD5_DIGESTSIZE);
free(ptr);
} /* END BLOCK */
break;
case mcsaDES:
default:
{
unsigned int crc;
unsigned int lword;
unsigned int rword;
unsigned int Seed;
int index;
Seed = (unsigned int)strtoul(CSKeyString,NULL,0);
crc = 0;
for (index = 0;index < BufSize1;index++)
{
crc = (unsigned int)__MSecDoCRC((unsigned short)crc,Buf1[index]);
} /* END for (index) */
for (index = 0;index < BufSize2;index++)
{
crc = (unsigned int)__MSecDoCRC((unsigned short)crc,Buf2[index]);
} /* END for (index) */
lword = crc;
rword = Seed;
__MSecPSDES(&lword,&rword);
sprintf(Checksum,"%08x%08x",
(int)lword,
(int)rword);
} /* END BLOCK */
break;
} /* END switch(Algo) */
return(SUCCESS);
} /* END MSecGetChecksum2() */
int MSecHMACGetDigest(
unsigned char *CSKeyString, /* I */
int CSKeyLen, /* I */
unsigned char *DataString, /* I */
int DataLen, /* I */
char *CSString, /* O */
int MaxCSStringLen, /* I */
char *DigestString, /* O (optional) */
mbool_t TwoPass, /* I */
mbool_t Use64BitEncoding) /* I */
{
SHA1_CTX ictx;
SHA1_CTX octx;
unsigned char isha[SHA_DIGESTSIZE];
unsigned char osha[SHA_DIGESTSIZE];
unsigned char key[SHA_DIGESTSIZE];
unsigned char buf[SHA_BLOCKSIZE];
unsigned char osha2[SHA_DIGESTSIZE];
int index;
char tmpBuf[SHA_DIGESTSIZE << 1];
unsigned char *DPtr;
int DLen;
#ifndef __MPROD
const char *FName = "MSecHMACGetDigest";
MDB(6,fSTRUCT) MLog("%s(%s,%d,%s,%d,CSString,%d,DigestString,%s,%s)\n",
FName,
(CSKeyString != NULL) ? (char *)CSKeyString : "NULL",
CSKeyLen,
(DataString != NULL) ? (char *)DataString : "NULL",
DataLen,
MaxCSStringLen,
MBool[TwoPass],
MBool[Use64BitEncoding]);
#endif /* !__MPROD */
/* create hash */
if (TwoPass == TRUE)
{
SHA1_CTX tctx;
__MSecSHA1Init(&tctx);
__MSecSHA1Update(&tctx,DataString,DataLen);
__MSecSHA1Final(osha2,&tctx);
if (DigestString != NULL)
{
/* encode digest */
if (Use64BitEncoding == TRUE)
{
MSecBufTo64BitEncoding(
(char *)osha2,
SHA_DIGESTSIZE,
DigestString);
}
else
{
MSecBufToHexEncoding(
(char *)osha2,
SHA_DIGESTSIZE,
DigestString);
}
} /* END if (DigestValue != NULL) */
DPtr = osha2;
DLen = SHA_DIGESTSIZE;
} /* END if (CSKeyString == NULL) */
else
{
DPtr = DataString;
DLen = DataLen;
}
if (CSKeyLen > SHA_BLOCKSIZE)
{
SHA1_CTX tctx;
__MSecSHA1Init(&tctx);
__MSecSHA1Update(&tctx,CSKeyString,CSKeyLen);
__MSecSHA1Final(key,&tctx);
CSKeyString = key;
CSKeyLen = SHA_DIGESTSIZE;
}
/**** inner digest ****/
__MSecSHA1Init(&ictx) ;
/* pad the key for inner digest */
for (index = 0;index < CSKeyLen;index++)
{
buf[index] = CSKeyString[index] ^ 0x36;
}
for (index = CSKeyLen;index < SHA_BLOCKSIZE;index++)
{
buf[index] = 0x36;
}
__MSecSHA1Update(&ictx,buf,SHA_BLOCKSIZE);
__MSecSHA1Update(&ictx,DPtr,DLen);
__MSecSHA1Final(isha,&ictx);
/**** outer digest ****/
__MSecSHA1Init(&octx) ;
/* pad the key for outer digest */
for (index = 0;index < CSKeyLen;index++)
{
buf[index] = CSKeyString[index] ^ 0x5C;
}
for (index = CSKeyLen;index < SHA_BLOCKSIZE;index++)
{
buf[index] = 0x5C;
}
__MSecSHA1Update(&octx,buf,SHA_BLOCKSIZE);
__MSecSHA1Update(&octx,isha,SHA_DIGESTSIZE);
__MSecSHA1Final(osha,&octx);
/* truncate and encode digest */
__MSecHMACTruncate(
(char *)osha,
tmpBuf,
MIN(SHA_DIGESTSIZE,MaxCSStringLen));
if (Use64BitEncoding == TRUE)
{
MSecBufTo64BitEncoding(
tmpBuf,
MIN(SHA_DIGESTSIZE,MaxCSStringLen),
CSString);
}
else
{
MSecBufToHexEncoding(
tmpBuf,
MIN(SHA_DIGESTSIZE,MaxCSStringLen),
CSString);
}
return(SUCCESS);
} /* END MSecHMACGetDigest() */
void __MSecHMACTruncate(
char *d1, /* data to be truncated */
char *d2, /* truncated data */
int len) /* length in bytes to keep */
{
int i;
#ifndef __MPROD
const char *FName = "__MSecHMACTruncate";
MDB(9,fSTRUCT) MLog("%s(d1,d2,%d)\n",
FName,
len);
#endif /* !__MPROD */
for (i = 0;i < len;i++)
{
d2[i] = d1[i];
} /* END for (i) */
return;
} /* END __MSecHMACTruncate() */
static void __MSecSHA1Transform(
MUINT4 state[5], /* I */
unsigned char buffer[64]) /* I */
{
/* hash a single 512-bit block. This is the core of the algorithm. */
MUINT4 a,b,c,d,e;
unsigned char workspace[64];
CHAR64LONG16 *block = (CHAR64LONG16*)workspace;
#ifndef __BMPROD
const char *FName = "__MSecSHA1Transform";
MDB(9,fSTRUCT) MLog("%s(context)\n",
FName);
#endif /* !__BMPROD */
memcpy(block,buffer,64);
/* copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* clear variables */
a = b = c = d = e = 0;
memset(block,0,64);
return;
} /* END __MSecSHA1Transform() */
void __MSecSHA1Init(
SHA1_CTX* context) /* O */
{
#ifndef __MPROD
const char *FName = "__MSecSHA1Init";
MDB(9,fSTRUCT) MLog("%s(context)\n",
FName);
#endif /* !__MPROD */
/* initialize new context */
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
return;
} /* END __MSecSHA1Init() */
void __MSecSHA1Update(
SHA1_CTX *Context,
unsigned char *Data,
MUINT4 DataLen)
{
MUINT4 i,j;
#ifndef __MPROD
const char *FName = "__MSecSHA1Update";
MDB(10,fSTRUCT) MLog("%s(Context,Data,DataLen)\n",
FName);
#endif /* !__MPROD */
j = (Context->count[0] >> 3) & 63;
if ((Context->count[0] += DataLen << 3) < (DataLen << 3))
Context->count[1]++;
Context->count[1] += (DataLen >> 29);
if ((j + DataLen) > 63)
{
i = 64 - j;
memcpy(&Context->buffer[j],Data,i);
__MSecSHA1Transform(Context->state,Context->buffer);
for (;i + 63 < DataLen;i += 64)
{
__MSecSHA1Transform(Context->state, &Data[i]);
} /* END for() */
j = 0;
}
else
{
i = 0;
}
memcpy(&Context->buffer[j],&Data[i],DataLen - i);
return;
} /* END __MSecSHA1Update() */
void __MSecSHA1Final(
unsigned char digest[20],
SHA1_CTX *context)
{
/* add padding and return the message digest. */
MUINT4 i;
unsigned char finalcount[8];
#ifndef __MPROD
const char *FName = "__MSecSHA1Final";
MDB(9,fSTRUCT) MLog("%s(digest,context)\n",
FName);
#endif /* !__MPROD */
for (i = 0;i < 8;i++)
{
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
} /* END for (i) */
__MSecSHA1Update(context,(unsigned char *)"\200",1);
while ((context->count[0] & 504) != 448)
{
__MSecSHA1Update(context, (unsigned char *)"\0", 1);
}
__MSecSHA1Update(context,finalcount,8);
for (i = 0;i < 20;i++)
{
digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
} /* END for (i) */
/* reset variables */
i = 0;
memset(context->buffer,0,64);
memset(context->state,0,20);
memset(context->count,0,8);
memset(finalcount,0,8);
return;
} /* END __MSecSHA1Final() */
int MSecMD5GetDigest(
char *CSKeyString, /* I */
int CSKeyLen, /* I */
char *DataString, /* I */
int DataLen, /* I */
char *CSString, /* O */
int MaxCSStringLen) /* O */
{
int index;
int len;
char tmpBuf[MMAX_BUFFER];
char MD5Sum[MMD5_DIGESTSIZE + 2];
char *ptr = NULL;
#ifndef __MPROD
const char *FName = "MSecMD5GetDigest";
MDB(2,fSTRUCT) MLog("%s(CSKeyString,CSKeyLen,DString,DLen,CSString,MaxCSLen)\n",
FName);
#endif /* !__MPROD */
if ((CSKeyString == NULL) ||
(DataString == NULL) ||
(CSString == NULL))
{
return(FAILURE);
}
/* NOTE: MD5(SrcBuf,strlen(SrcBuf),tmpLine); */
CSString[0] = '\0';
len = strlen(CSKeyString) + 1 + strlen(DataString);
sprintf(tmpBuf,"%s%s",
DataString,
CSKeyString);
#ifdef __MMD5
ptr = MD5(
(unsigned char *)tmpBuf,
(unsigned long)strlen(tmpBuf),
MD5Sum);
#endif /* __MMD5 */
if (ptr == NULL)
{
return(FAILURE);
}
for (index = 0;index < MMD5_DIGESTSIZE;index++)
{
sprintf(CSString,"%s%02x",
CSString,
(unsigned char)MD5Sum[index]);
} /* END for (index) */
strcat(CSString,"\n");
return(SUCCESS);
} /* END MSecMD5GetDigest() */
int __MSecPSDES(
unsigned int *lword,
unsigned int *irword)
{
int index;
unsigned int ia;
unsigned int ib;
unsigned int iswap;
unsigned int itmph;
unsigned int itmpl;
static unsigned int c1[MAX_MDESCKSUM_ITERATION] = {
(unsigned int)0xcba4e531,
(unsigned int)0x537158eb,
(unsigned int)0x145cdc3c,
(unsigned int)0x0d3fdeb2 };
static unsigned int c2[MAX_MDESCKSUM_ITERATION] = {
(unsigned int)0x12be4590,
(unsigned int)0xab54ce58,
(unsigned int)0x6954c7a6,
(unsigned int)0x15a2ca46 };
itmph = 0;
itmpl = 0;
for (index = 0;index < MAX_MDESCKSUM_ITERATION;index++)
{
iswap = *irword;
ia = iswap ^ c1[index];
itmpl = ia & 0xffff;
itmph = ia >> 16;
ib = (itmpl * itmpl) + ~(itmph * itmph);
ia = (ib >> 16) | ((ib & 0xffff) << 16);
*irword = (*lword) ^ ((ia ^ c2[index]) + (itmpl * itmph));
*lword = iswap;
}
return(SUCCESS);
} /* END __MSecPSDES() */
unsigned short __MSecDoCRC(
unsigned short crc,
unsigned char val)
{
int index;
unsigned int ans;
ans = (crc ^ val << 8);
for (index = 0;index < 8;index++)
{
if (ans & 0x8000)
ans = (ans << 1) ^ 4129;
else
ans <<= 1;
} /* END for (index) */
return((unsigned short)ans);
} /* END __MSecDoCRC() */
int MSecTestChecksum(
char *TLine) /* I */
{
char *CSKey;
char *Msg;
char *AType;
char *TokPtr;
char CSBuf[MMAX_LINE];
char Digest[MMAX_LINE];
int rc;
enum MChecksumAlgoEnum AIndex;
if (TLine == NULL)
{
return(FAILURE);
}
/* FORMAT: <KEY>,<ALGO>,<MSG> */
CSKey = MUStrTok(TLine,",",&TokPtr);
AType = MUStrTok(NULL,",",&TokPtr);
Msg = MUStrTok(NULL,"\n",&TokPtr);
AIndex = (enum MChecksumAlgoEnum)MUGetIndex(AType,MCSAlgoType,FALSE,0);
Digest[0] = '\0';
rc = MSecGetChecksum(
Msg,
strlen(Msg),
CSBuf,
Digest,
AIndex,
CSKey);
fprintf(stderr,"CS: '%s'/'%s'\n",
CSBuf,
Digest);
exit(rc);
/*NOTREACHED*/
return(SUCCESS);
} /* END MSecTestChecksum() */
int MSecBufToHexEncoding(
char *IBuf, /* I */
int IBufLen, /* I */
char *OBuf) /* O */
{
int index;
if ((IBuf == NULL) || (OBuf == NULL))
{
return(SUCCESS);
}
OBuf[0] = '\0';
for (index = 0;index < IBufLen;index++)
{
sprintf(OBuf,"%s%02x",
OBuf,
(unsigned char)IBuf[index]);
} /* END for (index) */
return(SUCCESS);
} /* END MSecBufToHexEncoding() */
static char CList[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char CDList[256] = {
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,62, 00,00,00,63,
52,53,54,55, 56,57,58,59, 60,61,00,00, 00,00,00,00,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,00, 00,00,00,00,
00,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00,
00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, };
int MSecBufTo64BitEncoding(
char *IBuf, /* I */
int IBufLen, /* I */
char *OBuf) /* O */
{
int index;
int cindex;
int block;
int slack;
int end;
char tmpBuf[5];
short val;
if ((IBuf == NULL) || (OBuf == NULL))
{
return(SUCCESS);
}
tmpBuf[4] = '\0';
OBuf[0] = '\0';
for (index = 0;index < IBufLen;index += 3)
{
block = 0;
slack = IBufLen - index - 1;
end = MIN(2,slack);
for (cindex = 0;cindex <= end;cindex++)
{
block +=
((unsigned char)IBuf[index + cindex] << (8 * (2 - cindex)));
} /* END for (cindex) */
for (cindex = 0;cindex < 4;cindex++)
{
val = (block >> (6 * (3 - cindex))) & 0x003f;
tmpBuf[cindex] = CList[val];
} /* END for (cindex) */
if (slack < 2)
{
tmpBuf[3] = '=';
if (slack < 1)
tmpBuf[2] = '=';
}
strcat(OBuf,tmpBuf);
} /* END for (index) */
return(SUCCESS);
} /* END MSecBufTo64BitEncoding() */
int MSecCompBufTo64BitEncoding(
char *IBuf,
int IBufLen,
char *OBuf) /* size = X */
{
int IIndex = 0;
int OIndex = 0;
if ((OBuf == NULL) || (IBuf == NULL))
{
return(FAILURE);
}
do
{
OBuf[OIndex++] = CList[(IBuf[IIndex] >> 2) & 0x3f];
OBuf[OIndex++] = CList[((IBuf[IIndex] << 4) & 0x30) | ((IBuf[IIndex + 1] >> 4) & 0x0f)];
if (IIndex + 1 < IBufLen)
OBuf[OIndex++] = CList[((IBuf[IIndex + 1] << 2) & 0x3c) | ((IBuf[IIndex + 2] >> 6) & 0x03)];
else
OBuf[OIndex++] = '=';
if (IIndex + 2 < IBufLen)
OBuf[OIndex++] = CList[((IBuf[IIndex + 2]) & 0x3f)];
else
OBuf[OIndex++] = '=';
IIndex += 3;
} while (IIndex < IBufLen);
OBuf[OIndex++] = '\0';
return(SUCCESS);
} /* MSecCompBufTo64BitEncoding() */
int MSecComp64BitToBufDecoding(
char *IBuf,
int IBufLen,
char *OBuf,
int *OBufLen)
{
int IIndex = 0;
int OIndex = 0;
if ((OBuf == NULL) || (IBuf == NULL))
{
return(FAILURE);
}
do
{
OBuf[OIndex++] = ((CDList[(int)IBuf[IIndex]] << 2 ) & 0xfc ) | ((CDList[(int)IBuf[IIndex+1]] >> 4 ) & 0x03 );
OBuf[OIndex++] = ((CDList[(int)IBuf[IIndex+1]] << 4 ) & 0xf0 ) | ((CDList[(int)IBuf[IIndex+2]] >> 2 ) & 0x0f );
OBuf[OIndex++] = ((CDList[(int)IBuf[IIndex+2]] << 6 ) & 0xc0 ) | ((CDList[(int)IBuf[IIndex+3]]));
IIndex += 4;
} while (IIndex < IBufLen);
if (OBufLen != NULL)
*OBufLen = OIndex;
return(SUCCESS);
} /* MSecComp64BitToBufDecoding() */
#define N 16
#define noErr 0
#define DATAERROR -1
#define KEYBYTES 8
#define subkeyfilename "Blowfish.dat"
unsigned long P[N + 2];
unsigned long S[4][256];
FILE* SubkeyFile;
short __MSecBlowfishOpenSubkeyFile(void) /* read only */
{
short error;
error = noErr;
if ((SubkeyFile = fopen(subkeyfilename,"rb")) == NULL)
{
error = DATAERROR;
}
return(error);
} /* END __MSecBlowfishOpenSubkeyFile() */
unsigned long __MSecBlowfishF(
mulong x) /* I */
{
unsigned short a;
unsigned short b;
unsigned short c;
unsigned short d;
unsigned long y;
d = x & 0x00FF;
x >>= 8;
c = x & 0x00FF;
x >>= 8;
b = x & 0x00FF;
x >>= 8;
a = x & 0x00FF;
/* y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d]; */
y = S[0][a] + S[1][b];
y ^= S[2][c];
y += S[3][d];
return(y);
} /* END __MSecBlowfishF() */
void MSecBlowfishEncipher(
mulong *xl, /* I (modified) */
mulong *xr) /* I (modified) */
{
unsigned long Xl;
unsigned long Xr;
unsigned long temp;
short i;
Xl = *xl;
Xr = *xr;
for (i = 0;i < N;++i)
{
Xl = Xl ^ P[i];
Xr = __MSecBlowfishF(Xl) ^ Xr;
temp = Xl;
Xl = Xr;
Xr = temp;
} /* END for (i) */
temp = Xl;
Xl = Xr;
Xr = temp;
Xr = Xr ^ P[N];
Xl = Xl ^ P[N + 1];
*xl = Xl;
*xr = Xr;
return;
} /* END MSecBlowfishEncipher() */
void MSecBlowfishDecipher(
mulong *xl, /* I (modified) */
mulong *xr) /* I (modified) */
{
unsigned long Xl;
unsigned long Xr;
unsigned long temp;
short i;
Xl = *xl;
Xr = *xr;
for (i = N + 1; i > 1; --i)
{
Xl = Xl ^ P[i];
Xr = __MSecBlowfishF(Xl) ^ Xr;
/* Exchange Xl and Xr */
temp = Xl;
Xl = Xr;
Xr = temp;
} /* END for (i) */
/* Exchange Xl and Xr */
temp = Xl;
Xl = Xr;
Xr = temp;
Xr = Xr ^ P[1];
Xl = Xl ^ P[0];
*xl = Xl;
*xr = Xr;
return;
} /* END MSecBlowfishDecipher() */
short MSecBlowfishInitialize(
char *Key, /* I */
short KeyBytes) /* I */
{
short i;
short j;
short k;
short error;
short numread;
unsigned long data;
unsigned long datal;
unsigned long datar;
/* First, open the file containing the array initialization data */
error = __MSecBlowfishOpenSubkeyFile();
if (error == noErr)
{
for (i = 0;i < N + 2;++i)
{
numread = fread(&data,4,1,SubkeyFile);
#ifdef little_endian /* Eg: Intel We want to process things in byte */
/* order, not as rearranged in a longword */
data = ((data & 0xFF000000) >> 24) |
((data & 0x00FF0000) >> 8) |
((data & 0x0000FF00) << 8) |
((data & 0x000000FF) << 24);
#endif
if (numread != 1)
{
return(DATAERROR);
}
else
{
P[i] = data;
}
} /* END for (i) */
for (i = 0;i < 4;++i)
{
for (j = 0;j < 256;++j)
{
numread = fread(&data,4,1,SubkeyFile);
#ifdef little_endian /* Eg: Intel We want to process things in byte */
/* order, not as rearranged in a longword */
data = ((data & 0xFF000000) >> 24) |
((data & 0x00FF0000) >> 8) |
((data & 0x0000FF00) << 8) |
((data & 0x000000FF) << 24);
#endif
if (numread != 1)
{
return(DATAERROR);
}
else
{
S[i][j] = data;
}
}
}
fclose(SubkeyFile);
j = 0;
for (i = 0;i < N + 2;++i)
{
data = 0x00000000;
for (k = 0;k < 4;++k)
{
data = (data << 8) | Key[j];
j = j + 1;
if (j >= KeyBytes)
{
j = 0;
}
}
P[i] = P[i] ^ data;
} /* END for (i) */
datal = 0x00000000;
datar = 0x00000000;
for (i = 0;i < N + 2;i += 2)
{
MSecBlowfishEncipher(&datal,&datar);
P[i] = datal;
P[i + 1] = datar;
}
for (i = 0;i < 4;++i)
{
for (j = 0;j < 256;j += 2)
{
MSecBlowfishEncipher(&datal,&datar);
S[i][j] = datal;
S[i][j + 1] = datar;
}
}
}
else
{
printf("Unable to open subkey initialization file : %d\n",
error);
}
return(error);
} /* END MSecBlowfishInitialize() */
#define FLAG_Copied 0x80
#define FLAG_Compress 0x40
int MSecCompressionGetMatch(
unsigned char *Source,
unsigned int X,
unsigned int SourceSize,
int *Hash,
unsigned int *Size,
int *Pos) /* O */
{
unsigned int HashValue = (40543L*((((Source[X] << 4) ^ Source[X+1]) << 4) ^ Source[X+2]) >> 4) & 0xfff;
*Pos = Hash[HashValue];
Hash[HashValue] = X;
if ((*Pos != -1) && ((X - *Pos) < 4096))
{
for (*Size = 0;
((*Size < 18) &&
(Source[X + *Size] == Source[*Pos + *Size]) &&
((X + *Size) < SourceSize));
(*Size)++);
return(*Size >= 3);
}
return(FALSE);
} /* END MSecCompressionGetMatch() */
int MSecCompress(
unsigned char *SrcString, /* I */
unsigned int SrcSize, /* I */
unsigned char *DstString, /* O (optional,if NULL, populate SrcString) */
char *EKey) /* I (optional - enables encryption when present) */
{
static char *LocalDstString = NULL;
static int LocalDstSize = 0;
char *Dest;
int Hash[4096];
int NewLength;
unsigned int Key;
unsigned int Size;
unsigned int Pos;
unsigned int Command;
unsigned int X = 0;
unsigned int Y = 9;
unsigned int Z = 3;
unsigned char Bit = 0;
#ifndef __MPROD
const char *FName = "MSecCompress";
MDB(2,fSTRUCT) MLog("%s(SrcString,%d,DstString,%s)\n",
FName,
SrcSize,
(EKey != NULL) ? "EKey" : "NULL");
#endif /* !__MPROD */
NewLength = (int)(ceil(SrcSize / 3.0) * 4) + 1;
MDB(7,fSTRUCT) MLog("INFO: compressing data (Original Size - %d)\n",
SrcSize);
NewLength = (int)(ceil(SrcSize / 3.0) * 4) + 1;
if (DstString == NULL)
{
/* use static local buffer */
if (LocalDstString == NULL)
{
LocalDstString = (char *)malloc(NewLength);
LocalDstSize = NewLength;
}
else if (LocalDstSize < NewLength)
{
LocalDstString = (char *)realloc(LocalDstString,NewLength);
LocalDstSize = NewLength;
}
Dest = LocalDstString;
}
else
{
Dest = (char *)DstString;
}
for (Key = 0;Key < 4096;Key++)
Hash[Key] = -1;
Dest[0] = FLAG_Compress;
/* Y = 9, initialize Dest up Y */
Dest[1] = '\0';
Dest[2] = '\0';
Dest[3] = '\0';
Dest[4] = '\0';
Dest[5] = '\0';
Dest[6] = '\0';
Dest[7] = '\0';
Dest[8] = '\0';
Dest[9] = '\0';
for (;(X < SrcSize) && (Y <= SrcSize);)
{
if (Bit > 15)
{
Dest[Z++] = (Command >> 8) & 0x00ff;
Dest[Z] = Command & 0x00ff;
Z = Y;
Bit = 0;
Y += 2;
}
for (Size = 1;
(SrcString[X] == SrcString[X + Size]) && (Size < 0x0fff) && (X + Size < SrcSize);
Size++);
if (Size >= 16)
{
Dest[Y++] = 0;
Dest[Y++] = ((Size - 16) >> 8) & 0x00ff;
Dest[Y++] = (Size - 16) & 0x00ff;
Dest[Y++] = SrcString[X];
X += Size;
Command = (Command << 1) + 1;
}
else if (MSecCompressionGetMatch(SrcString,X,SrcSize,Hash,&Size,(int *)&Pos))
{
Key = ((X-Pos) << 4) + (Size - 3);
Dest[Y++] = (Key >> 8) & 0x00ff;
Dest[Y++] = Key & 0x00ff;
X += Size;
Command = (Command << 1) + 1;
}
else
{
Dest[Y++] = SrcString[X++];
Command = (Command << 1);
}
Bit++;
} /* END for (X) */
if (Dest == LocalDstString)
{
/* pad end of data */
Dest[Y] = '\0';
Dest[Y + 1] = '\0';
}
Command <<= (16 - Bit);
Dest[Z++] = (Command >> 8) & 0x00ff;
Dest[Z] = Command & 0x00ff;
if (Y > SrcSize)
{
for (Y = 0;Y < SrcSize;Dest[Y + 1] = SrcString[Y++]);
Dest[0] = FLAG_Copied;
return(SrcSize + 1);
}
if (EKey != NULL)
{
MSecEncryption(Dest,EKey,Y);
}
MSecCompBufTo64BitEncoding(
Dest,
Y,
(DstString == NULL) ? (char *)SrcString : (char *)DstString);
MDB(7,fSTRUCT) MLog("INFO: compressed data size - %d\n",
(DstString == NULL) ? strlen((char *)SrcString) : strlen((char *)DstString));
return(SUCCESS);
} /* END MSecCompress() */
int MSecDecompress(
unsigned char *SrcString, /* I */
unsigned int SrcSize, /* I */
unsigned char *SDstBuf, /* I (optional) */
unsigned int SDstSize, /* I (required if DstBuf set) */
unsigned char **DDstBuf, /* O (optional) */
char *EKey) /* I (optional - encryption enabled when present) */
{
static unsigned char *tmpBuf = NULL;
static unsigned char *OutBuf = NULL;
static int OutBufSize = 0;
unsigned int DstSize;
unsigned int NewLength;
unsigned int X = 9;
unsigned int Y = 0;
unsigned int Pos;
unsigned int Size;
unsigned int K;
int Command;
unsigned char *DstString;
unsigned char Bit = 16;
if ((SrcString == NULL) || (SrcSize <= 0))
{
return(FAILURE);
}
if ((SDstBuf != NULL) && (SDstSize > 0))
{
DstString = SDstBuf;
DstSize = SDstSize;
}
else if (DDstBuf != NULL)
{
if ((OutBuf == NULL) &&
((OutBuf = (unsigned char *)malloc(MMAX_BUFFER)) == NULL))
{
return(FAILURE);
}
else
{
OutBufSize = MMAX_BUFFER;
}
*DDstBuf = NULL;
DstString = OutBuf;
DstSize = OutBufSize;
}
else
{
return(FAILURE);
}
DstString[0] = '\0';
NewLength = SrcSize;
if (tmpBuf == NULL)
{
if ((tmpBuf = (unsigned char *)malloc(NewLength)) == NULL)
{
return(FAILURE);
}
}
else
{
if (sizeof(tmpBuf) < NewLength)
{
if ((tmpBuf = (unsigned char *)realloc(tmpBuf,NewLength)) == NULL)
{
return(FAILURE);
}
}
}
tmpBuf[0] = '\0';
MSecComp64BitToBufDecoding((char *)SrcString,(int)SrcSize,(char *)tmpBuf,(int *)&SrcSize);
if (EKey != NULL)
MSecEncryption((char *)tmpBuf,EKey,SrcSize);
Command = (tmpBuf[3] << 8) + tmpBuf[4];
/*
if (tmpBuf[0] == FLAG_Copied)
{
for (Y = 1; Y < SrcSize; DstString[Y-1] = tmpBuf[Y++]);
return(SrcSize-1);
}
*/
for (;X < SrcSize;)
{
if (Bit == 0)
{
Command = (tmpBuf[X++] << 8);
Command += tmpBuf[X++];
Bit = 16;
}
if (Command & 0x8000)
{
Pos = (tmpBuf[X++] << 4);
Pos += (tmpBuf[X] >> 4);
if (Pos)
{
Size = (tmpBuf[X++] & 0x0f) + 3;
if ((Y + Size) > DstSize)
{
/* bounds check */
if (DDstBuf != NULL)
{
DstSize <<= 1;
if ((OutBuf = (unsigned char *)realloc(OutBuf,DstSize)) == NULL)
{
return(FAILURE);
}
DstString = OutBuf;
}
else
{
return(FAILURE);
}
}
for (K = 0; K < Size;K++)
{
DstString[Y + K] = DstString[Y - Pos + K];
}
Y += Size;
}
else
{
Size = (tmpBuf[X++] << 8);
Size += tmpBuf[X++] + 16;
if ((Y + Size) > DstSize)
{
/* bounds check */
if (DDstBuf != NULL)
{
DstSize <<= 1;
if ((OutBuf = (unsigned char *)realloc(OutBuf,DstSize)) == NULL)
{
return(FAILURE);
}
DstString = OutBuf;
}
else
{
return(FAILURE);
}
}
for (K = 0;K < Size;DstString[Y + K++] = tmpBuf[X]);
X++;
Y += Size;
}
}
else
{
if (Y >= DstSize)
{
/* bounds check */
if (DDstBuf != NULL)
{
DstSize <<= 1;
if ((OutBuf = (unsigned char *)realloc(OutBuf,DstSize)) == NULL)
{
return(FAILURE);
}
DstString = OutBuf;
}
else
{
return(FAILURE);
}
}
DstString[Y++] = tmpBuf[X++];
} /* END else () */
Command <<= 1;
Bit--;
} /* END for() */
/* terminate buffer */
if (Y < DstSize)
OutBuf[Y] = '\0';
if (DDstBuf != NULL)
{
*DDstBuf = OutBuf;
}
return(SUCCESS);
} /* END MSecDecompress() */
int MSecEncryption(
char *SrcString,
char *Key,
int SrcSize)
{
int r;
char *cp_val;
char *cp_key;
char result;
r = 0;
if((SrcString != NULL) && (Key != NULL))
{
cp_val = SrcString;
cp_key = Key;
while(r < SrcSize)
{
result = *cp_val ^ *cp_key;
*cp_val = result;
cp_val++;
cp_key++;
if(*cp_key == '\0') cp_key = Key;
r++;
}
}
return(SUCCESS);
} /* END MSecEncryption() */
/* END MSec.c */