#include "ckutilsPlatform.h"
#include "Crypt.h"
#include "feeCipherFile.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static unsigned char *dataPool;
#undef BOOL
#undef YES
#undef NO
#define BOOL int
#define YES 1
#define NO 0
#define LOOPS_DEF 100
#define MIN_EXP 2
#define MAX_EXP 3
#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT
#define MIN_OFFSET 0
#define MAX_OFFSET 99
#define PASSWD_LENGTH 10
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" l==loops (default=%d)\n", LOOPS_DEF);
printf(" n=minExp (default=%d)\n", MIN_EXP);
printf(" x=maxExp (default=max=%d)\n", MAX_EXP);
printf(" D=depth (default=%d)\n", DEPTH_DEFAULT);
printf(" N=minOffset (default=%d)\n", MIN_OFFSET);
printf(" q(uiet) v(erbose)\n");
printf(" h(elp) I(ncrementing offset)\n");
exit(1);
}
static int genRand(int min, int max)
{
if(max == min)
return(max);
else
return(min + (RAND() % (max-min+1)));
}
#define MIN_ASCII ' '
#define MAX_ASCII '~'
static void genPasswd(unsigned char *passwd,
unsigned passwdLen, BOOL ascii)
{
unsigned *ip = (unsigned *)passwd;
unsigned intCount = passwdLen / 4;
int i;
unsigned char *cp;
unsigned residue = passwdLen & 0x3;
char ac;
if(ascii) {
cp = passwd;
ac = MIN_ASCII;
for(i=0; i<passwdLen; i++) {
*cp++ = ac++;
if(ac > MAX_ASCII) {
ac = MIN_ASCII;
}
}
}
else {
for (i=0; i<intCount; i++) {
*ip++ = RAND();
}
cp = (unsigned char *)ip;
for(i=0; i<residue; i++) {
*cp = (unsigned char)RAND();
}
}
}
typedef enum {
DT_Random,
DT_Zero,
DT_ASCII,
DT_None
} dataType;
static void fillDataPool(unsigned size, dataType type)
{
#ifdef __LITTLE_ENDIAN__
unsigned *ip;
unsigned intCount;
unsigned residue;
#endif
unsigned char *cp;
int i;
unsigned char ac;
switch(type) {
case DT_Zero:
bzero(dataPool, size);
break;
case DT_ASCII:
ac = MIN_ASCII;
cp = dataPool;
for(i=0; i<size; i++) {
*cp++ = ac++;
if(ac > MAX_ASCII) {
ac = MIN_ASCII;
}
}
break;
case DT_Random:
#ifdef __LITTLE_ENDIAN__
intCount = size >> 2;
ip = (unsigned *)dataPool;
for(i=0; i<intCount; i++) {
*ip++ = RAND();
}
residue = size & 0x3;
cp = (unsigned char *)ip;
for(i=0; i<residue; i++) {
*cp++ = (unsigned char)RAND();
}
#else __LITTLE_ENDIAN__
cp = dataPool;
for(i=0; i<size; i++) {
*cp++ = (char)RAND();
}
#endif __LITTLE_ENDIAN__
break;
case DT_None:
printf("fillDataPool(DT_None)\n");
exit(1);
}
}
static unsigned dataSizeFromExp(unsigned maxExp)
{
int size = 1;
while(maxExp--) { size *= 10;
}
return size;
}
static int sizeOffset = MIN_OFFSET;
static unsigned char *genData(unsigned minExp,
unsigned maxExp,
dataType type,
BOOL incrOffset,
unsigned minOffset,
unsigned *dataLen) {
int exp;
int offset;
int size;
exp = genRand(minExp, maxExp);
if(incrOffset) {
offset = sizeOffset++;
if(sizeOffset == MAX_OFFSET) {
sizeOffset = minOffset;
}
}
else {
offset = genRand(minOffset, MAX_OFFSET);
}
size = dataSizeFromExp(exp) + offset;
if(type != DT_None) {
fillDataPool(size, type);
}
*dataLen = size;
return dataPool;
}
static feePubKey genPrivKey(const unsigned char *privKeyData,
unsigned privDataLen,
int depth)
{
feePubKey privKey; feeReturn frtn;
privKey = feePubKeyAlloc();
frtn = feePubKeyInitFromPrivDataDepth(privKey,
(unsigned char *)privKeyData,
privDataLen,
depth,
1);
if(frtn) {
printf("pubKeyFromPrivDataDepth: Can't create new key (%s)\n",
feeReturnString(frtn));
exit(1);
}
return privKey;
}
static feePubKey genPubKey(feePubKey privKey)
{
feePubKey pubKey; feeReturn frtn;
char *pubString;
unsigned pubStringLen;
frtn = feePubKeyCreateKeyString(privKey, &pubString, &pubStringLen);
if(frtn) {
printf("feePubKeyCreateKeyString: Can't get key string (%s)\n",
feeReturnString(frtn));
exit(1);
}
pubKey = feePubKeyAlloc();
frtn = feePubKeyInitFromKeyString(pubKey, pubString, pubStringLen);
if(frtn) {
printf("feePubKeyInitFromKeyString: Can't create new key "
"(%s)\n",
feeReturnString(frtn));
feePubKeyFree(pubKey);
exit(1);
}
ffree(pubString);
return pubKey;
}
static char *stringFromEncrType(cipherFileEncrType encrType)
{
switch(encrType) {
case CFE_PublicDES: return "CFE_PublicDES";
case CFE_RandDES: return "CFE_RandDES";
case CFE_FEED: return "CFE_FEED";
case CFE_FEEDExp: return "CFE_FEEDExp";
default: return "Bogus encrType";
}
}
#define SIG_NO 0
#define SIG_YES 1
#define EXPLICIT_NO 0
#define EXPLICIT_YES 1
#define EXPLICIT_ERR 2
static void doTest(unsigned char *ptext,
unsigned ptextLen,
feePubKey myPrivKey,
feePubKey myPubKey,
feePubKey theirPrivKey,
feePubKey theirPubKey,
cipherFileEncrType encrType,
int doEnc64,
int doSig,
int doExplicitKey)
{
feeReturn frtn;
unsigned char *ctext;
unsigned ctextLen;
unsigned char *dectext;
unsigned dectextLen;
unsigned outUserData = 0x1234567;
unsigned inUserData;
cipherFileEncrType inEncrType;
feeSigStatus sigStatus;
int abort = 0;
char instr[100];
feeSigStatus expSigStatus = SS_PresentValid;
int valid64;
feePubKey sendPrivKey = myPrivKey;
feePubKey sendPubKey = myPubKey;
feePubKey recvPrivKey = theirPrivKey;
feePubKey recvPubKey = theirPubKey;
switch(encrType) {
case CFE_RandDES:
case CFE_FEEDExp:
if(!doSig) {
sendPrivKey = NULL; }
break;
case CFE_PublicDES:
case CFE_FEED:
break;
default:
printf("Hey bozo! Give me a real encrType!\n");
exit(1);
}
if(!doSig) {
sendPubKey = NULL; expSigStatus = SS_NotPresent;
}
else switch(doExplicitKey) {
case EXPLICIT_NO:
sendPubKey = NULL; break;
case EXPLICIT_YES:
break; case EXPLICIT_ERR:
if(feePubKeyIsEqual(myPubKey, theirPubKey)) {
printf("myPubKey = theirPubKey!\n");
goto errOut;
}
sendPubKey = theirPubKey; expSigStatus = SS_PresentInvalid;
break;
default:
printf("BOGUS doExplicitKey\n");
exit(1);
}
frtn = createCipherFile(sendPrivKey,
recvPubKey,
encrType,
ptext,
ptextLen,
doSig,
doEnc64,
outUserData,
&ctext,
&ctextLen);
if(frtn) {
printf("createCipherFile: %s\n", feeReturnString(frtn));
goto errOut;
}
valid64 = isValidEnc64(ctext, ctextLen);
if(valid64 != doEnc64) {
printf("valid64 mismatch! exp %d got %d\n", doEnc64, valid64);
abort = 1;
}
frtn = parseCipherFile(recvPrivKey,
sendPubKey,
ctext,
ctextLen,
doEnc64,
&inEncrType,
&dectext,
&dectextLen,
&sigStatus,
&inUserData);
if(frtn) {
printf("parseCipherFile: %s\n", feeReturnString(frtn));
goto errOut;
}
if(inEncrType != encrType) {
printf("encrType mismatch exp %d got %d\n",
encrType, inEncrType);
abort = 1;
}
if(inUserData != outUserData) {
printf("userData mismatch exp %d got %d\n",
outUserData, inUserData);
abort = 1;
}
if(sigStatus != expSigStatus) {
printf("Bad sigStatus exp %d got %d\n",
expSigStatus, sigStatus);
abort = 1;
}
if(ptextLen != dectextLen) {
printf("ptextLen mismatch exp %d got %d\n",
ptextLen, dectextLen);
abort = 1;
}
if(bcmp(ptext, dectext, ptextLen)) {
printf("Data Miscompare\n");
abort = 1;
}
ffree(dectext);
ffree(ctext);
if(!abort) {
return;
}
errOut:
printf("attach with debugger for more info; enter CR to quit: ");
gets(instr);
exit(1);
}
int main(int argc, char **argv)
{
int arg;
char *argp;
int loop;
unsigned char *ptext;
unsigned ptextLen;
unsigned char passwd1[PASSWD_LENGTH];
unsigned char passwd2[PASSWD_LENGTH];
int encrType;
int doEnc64;
feePubKey myPrivKey;
feePubKey theirPrivKey;
feePubKey myPubKey;
feePubKey theirPubKey;
unsigned maxSize;
unsigned loops = LOOPS_DEF;
BOOL seedSpec = NO;
unsigned seed;
BOOL quiet = NO;
BOOL verbose = NO;
unsigned minExp = MIN_EXP;
unsigned maxExp = MAX_EXP;
BOOL incrOffset = NO;
unsigned depth = DEPTH_DEFAULT;
unsigned minOffset = MIN_OFFSET;
#if macintosh
argc = ccommand(&argv);
#endif
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'l':
loops = atoi(&argp[2]);
break;
case 'n':
minExp = atoi(&argp[2]);
break;
case 'D':
depth = atoi(&argp[2]);
break;
case 'N':
minOffset = atoi(&argp[2]);
if(minOffset > MAX_OFFSET) {
minOffset = MIN_OFFSET;
}
sizeOffset = minOffset;
break;
case 'x':
maxExp = atoi(&argp[2]);
if(maxExp > MAX_EXP) {
usage(argv);
}
break;
case 's':
seed = atoi(&argp[2]);
seedSpec = YES;
break;
case 'I':
incrOffset = YES;
break;
case 'q':
quiet = YES;
break;
case 'v':
verbose = YES;
break;
case 'h':
default:
usage(argv);
}
}
if(seedSpec == NO) {
time((unsigned long *)(&seed));
}
SRAND(seed);
maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8;
dataPool = fmalloc(maxSize);
printf("Starting cfileTest: loops %d seed %d depth %d\n",
loops, seed, depth);
for(loop=1; ; loop++) {
ptext = genData(minExp, maxExp, DT_Random, incrOffset,
minOffset, &ptextLen);
if(!quiet) {
printf("..loop %d plaintext size %d\n", loop, ptextLen);
}
genPasswd(passwd1, PASSWD_LENGTH, NO); genPasswd(passwd2, PASSWD_LENGTH, NO);
myPrivKey = genPrivKey(passwd1, PASSWD_LENGTH, depth);
theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth);
myPubKey = genPubKey(myPrivKey);
theirPubKey = genPubKey(theirPrivKey);
for(encrType=CFE_PublicDES;
encrType<=CFE_FEEDExp;
encrType++) {
if(verbose) {
printf(" ..%s\n", stringFromEncrType(encrType));
}
for(doEnc64=0; doEnc64<2; doEnc64++) {
if(verbose) {
printf(" ..doEnc64 %d\n", doEnc64);
}
if(verbose) {
printf(" ..no sig\n");
}
doTest(ptext, ptextLen, myPrivKey, myPubKey,
theirPrivKey, theirPubKey,
encrType, doEnc64, SIG_NO, EXPLICIT_NO);
if(verbose) {
printf(" ..sig, implicit sendPubKey\n");
}
doTest(ptext, ptextLen, myPrivKey, myPubKey,
theirPrivKey, theirPubKey,
encrType, doEnc64, SIG_YES, EXPLICIT_NO);
if(verbose) {
printf(" ..sig, explicit sendPubKey\n");
}
doTest(ptext, ptextLen, myPrivKey, myPubKey,
theirPrivKey, theirPubKey,
encrType, doEnc64, SIG_YES, EXPLICIT_YES);
if(verbose) {
printf(" ..sig, force error\n");
}
doTest(ptext, ptextLen, myPrivKey, myPubKey,
theirPrivKey, theirPubKey,
encrType, doEnc64, SIG_YES, EXPLICIT_ERR);
}
}
feePubKeyFree(myPrivKey);
feePubKeyFree(myPubKey);
feePubKeyFree(theirPrivKey);
feePubKeyFree(theirPubKey);
if(loops) {
if(loop == loops) {
break;
}
}
}
if(!quiet) {
printf("cfile test complete\n");
}
return 0;
}