www.pudn.com > twofish-reference-c.zip > TST2FISH.C
/*************************************************************************** TST2FISH.C -- Test code for Twofish encryption Submitters: Bruce Schneier, Counterpane Systems Doug Whiting, Hi/fn John Kelsey, Counterpane Systems Chris Hall, Counterpane Systems David Wagner, UC Berkeley Code Author: Doug Whiting, Hi/fn Version 1.00 April 1998 Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved. Notes: * Tab size is set to 4 characters in this file * A random number generator is generated and used here, so that the same results can be generated on different platforms/compilers. * Command line arguments: -h or ? ==> give help message -lNN ==> set sanity count test loop count to NN -m ==> do full MCT generation -pPath ==> set file base path -r ==> set initial random seed based on time -tNN ==> perform timings with iteration count NN -rNN ==> set initial random seed to NN -v ==> read & verify files instead of creating them ***************************************************************************/ #include "aes.h" #include#include #include #include #include extern CONST char *moduleDescription; /* which module is running */ extern CONST char *modeString; /* which key schedule mode */ extern CONST int debugCompile; /* is external module compiled with debug? */ char CompilerName[8]= #if defined(__BORLANDC__) "BCC"; #elif defined(_MSC_VER) "MSC"; #elif defined(__WATCOMC__) "WAT"; #else "???"; #endif #if defined(__WATCOMC__) && defined(_M_IX86) && !defined(NO_TIMER) DWORD ReadTimeStampCounter(void); #pragma aux ReadTimeStampCounter = " db 0Fh,031h" value [eax] modify exact [eax edx] // RDTSC opcode #endif /* +***************************************************************************** * Constants/Macros/Tables -****************************************************************************/ typedef struct { FILE *f; /* the file being written/read */ int I; /* test number */ int keySize; /* key size in bits */ int gotDebugIO; /* got any debug IO? */ BYTE pt[BLOCK_SIZE/8]; /* plaintext */ BYTE ct[BLOCK_SIZE/8]; /* ciphertext */ keyInstance ki; /* use ki.keyDwords as key bits */ cipherInstance ci; /* use ci.iv as iv bits */ } testData; static char hexTab[] = "0123456789ABCDEF"; char filePath[80]= ""; int useAsm = 0; /* use assembly language */ int mctInner = MCT_INNER/100; int mctOuter = MCT_OUTER/10; int verify = 0; /* set to nonzero to read&verify files */ int debug = 0; /* debugging mode */ int verbose = 0; /* verbose output */ int quietVerify = 0; /* quiet during verify */ int timeIterCnt = 0; /* how many times to iterate for timing */ DWORD randBits[64]= {1}; /* use Knuth's additive generator */ int randPtr; testData * debugTD = NULL; /* for use with debugIO */ int CLKS_BYTE = 0; /* use clks/byte? (vs. clks/block) */ int FMT_LOG = 0; /* format for log file */ int CLK_MHZ = 200;/* default clock speed */ #define KEY_BITS_0 128 /* first key bit setting to test */ #define STEP_KEY_BITS ((MAX_KEY_BITS-KEY_BITS_0)/2) static char hexString[]= "0123456789ABCDEFFEDCBA987654321000112233445566778899AABBCCDDEEFF"; /* +***************************************************************************** * Functions -****************************************************************************/ DWORD Here(DWORD x) { unsigned int mask=~0U; return (* (((DWORD *)&x)-1)) & mask; } extern DWORD TwofishCodeSize(void); #ifdef USE_ASM int cdecl get_cpu_type(void); /* return CPU type */ #endif /* +***************************************************************************** * * Function Name: Rand * * Function: Generate random number * * Arguments: None. * * Return: New random number. * * Notes: Uses Knuth's additive generator, other magic * -****************************************************************************/ DWORD Rand(void) { if (randPtr >= 57) randPtr = 0; /* handle the ptr wrap */ randBits[randPtr] += randBits[(randPtr < 7) ? randPtr-7+57 : randPtr-7]; randBits[62]+= randBits[61]; randBits[63] = ROL(randBits[63],9) + 0x6F4ED7D0; /* very long period! */ return (randBits[randPtr++] ^ randBits[63]) + randBits[62]; } /* +***************************************************************************** * * Function Name: SetRand * * Function: Initialize random number seed * * Arguments: seed = new seed value * * Return: None. * * Notes: * -****************************************************************************/ void SetRand(DWORD seed) { int i; DWORD x; randPtr=0; for (i=x=0;i<64;i++) { randBits[i]=seed; x |= seed; /* keep track of lsb of all entries */ seed = ROL(seed,11) + 0x12345678; } if ((x & 1) == 0) /* insure maximal period by having at least one odd value */ randBits[0]++; for (i=0;i<1000;i++) Rand(); /* run it for a while */ randBits[63] = Rand(); randBits[62] = Rand(); randBits[61] = Rand() | 1; /* make it odd */ } /* +***************************************************************************** * * Function Name: ClearTestData * * Function: Initialize test data to all zeroes * * Arguments: t = pointer to testData structure * * Return: None. * * Notes: * -****************************************************************************/ void ClearTestData(testData *t) { t->gotDebugIO=0; memset(t->pt,0,BLOCK_SIZE/8); memset(t->ct,0,BLOCK_SIZE/8); memset(t->ci.iv32,0,BLOCK_SIZE/8); memset(t->ki.key32,0,MAX_KEY_BITS/8); memset(t->ki.keyMaterial,'0',sizeof(t->ki.keyMaterial)); #if defined(COMPILE_KEY) && defined(USE_ASM) t->ki.cSig1=t->ki.cSig2=0; #endif } /* +***************************************************************************** * * Function Name: FatalError * * Function: Output a fatal error message and exit * * Arguments: msg = fatal error description (printf string) * msg2 = 2nd parameter to printf msg * * Return: None. * * Notes: * -****************************************************************************/ void FatalError(CONST char *msg,CONST char *msg2) { printf("\nFATAL ERROR: "); printf(msg,msg2); exit(2); } /* +***************************************************************************** * * Function Name: GetTimer * * Function: Return a hi-frequency timer value * * Arguments: None * * Return: None. * * Notes: * -****************************************************************************/ DWORD GetTimer(void) { DWORD x; #if defined(__BORLANDC__) && defined(__WIN32__) && !defined(NO_TIMER) #define HI_RES_CLK 1 x=0; #pragma option -Od /* disable optimizations (it's a REAL hack!) */ __emit__(0x0F); __emit__(0x31); /* RDTSC opcode */ #pragma option -O. /* restore optimization setting */ #elif defined(_MSC_VER) && defined(_M_IX86) && !defined(NO_TIMER) #define HI_RES_CLK 1 _asm { _emit 0x0F _emit 0x31 mov x,eax }; #elif defined(__WATCOMC__) && defined(_M_IX86) && !defined(NO_TIMER) #define HI_RES_CLK 1 x = ReadTimeStampCounter(); #elif defined(CLOCKS_PER_SEC) x=clock(); #else #define CLOCKS_PER_SEC 1 /* very low resolution timer */ x=time(NULL); #endif return x; } /* +***************************************************************************** * * Function Name: TimeOps * * Function: Time encryption/decryption and print results * * Arguments: iterCnt = how many calls to make * * Return: None. * * Notes: None. * -****************************************************************************/ void TimeOps(int iterCnt) { enum { TEST_CNT = 3, BLOCK_CNT=64 }; int i,j,k,n,q; DWORD t0,t1,dt[8],minT; DWORD testTime[3][TEST_CNT]; testData t; BYTE text[BLOCK_CNT*(BLOCK_SIZE/8)]; static char *testName[TEST_CNT]={"BlockEncrypt:","BlockDecrypt:","reKeyEncrypt:"}; static char *atomName[TEST_CNT]={"block","block","call "}; static char *format [TEST_CNT]={"%10.1f/%s ","%10.1f/%s ","%10.1f/%s "}; static int denom [TEST_CNT]={BLOCK_CNT,BLOCK_CNT,1}; static int needSet [TEST_CNT]={1,1,0}; ClearTestData(&t); for (i=0;i t1-t0) minT = t1-t0; } testTime[q][n]=minT; } } /* now print all the results */ #ifdef HI_RES_CLK if (!FMT_LOG) { printf("\nCalibrate GetTimer(): ",t1-t0); for (i=0;i > (8*(q&3))); /* auto-Bswap! */ for (j=0;j = debug) exit(1); printf(";-------------------------------------------------\n"); } } } } debug=saveDebug; if (!quietVerify) printf(" OK\n"); } /* +***************************************************************************** * * Function Name: AES_FileIO * * Function: Output to file or verify file contents vs. string * * Arguments: f = opened file * s = string to output/compare (NULL-->reset, return) * errOK = do not fatalError on miscompare * * Return: Zero --> compare ok * * Notes: On miscompare, FatalError (unless errOK) * -****************************************************************************/ int AES_FileIO(FILE *f,CONST char *s,int errOK) { int i; static int lineNum=0; static int j=0; static char line[516]=""; if (s == NULL) /* starting new file */ { line[0]=j=lineNum=0; return 0; } if (!verify) { fprintf(f,s); return 0; } /* here to verify the file against the string */ for (i=0;s[i];i++) { while (line[j] == 0) { lineNum++; if (fgets(line,sizeof(line)-4,f) == NULL) { if ((s[i]=='\n') && (s[i+1]==0)) { line[0]=j=0; /* missing final eol is ok */ return 0; } FatalError("Unexpected EOF looking for %s",s); } if (verbose) printf(line); j=0; } if (s[i] != line[j]) { if ((s[i] == '\n') && ((i==0) || (s[i-1] == '\n'))) continue; /* blank line skip */ if (line[j] == '\n') {j++; continue; } if (!errOK) { char tmp[1024]; sprintf(tmp,"Miscompare at line #%d:\n%s\nlooking for\n\n%%s",lineNum,line); FatalError(tmp,s); } line[0]=j=0; /* let caller re-synch if desired */ return 1; /* return error flag */ } j++; } return 0; } /* +***************************************************************************** * * Function Name: AES_PutFileHeader * * Function: Output a text header for AES test file * * Arguments: fileName = name of file to create * testName = name of the specific test * * Return: Open FILE pointer * * Notes: If unable to create, gives FatalError * -****************************************************************************/ FILE *AES_PutFileHeader(CONST char *fileName,CONST char *testName) { char s[512]; FILE *f; sprintf(s,"%s%s",filePath,fileName); if (verify) { if (!quietVerify) printf("Verifying file %s",s); f=fopen(s,"rt"); AES_FileIO(NULL,NULL,0); /* reset file read state */ } else { printf("Creating file %s.\n",s); f=fopen(s,"wt"); } if (f == NULL) FatalError("Unable to open file '%s'",s); sprintf(s, "\n=========================\n" "\n" "FILENAME: \"%s\"\n" "\n" "%s\n" "\n" "Algorithm Name: TWOFISH\n" "Principal Submitter: Bruce Schneier, Counterpane Systems\n" "\n" "==========\n" "\n", fileName,testName); if (AES_FileIO(f,s,1)) { /* header mismatch */ if (!verify) FatalError("Miscompare while not verifying??",""); printf(" \tWARNING: header mismatch!"); fgets(s,sizeof(s)-4,f); do { /* skip rest of "bad" header */ if (fgets(s,sizeof(s)-4,f) == NULL) break; /* end of file? */ } while ((s[0] != '=') || (s[1] != '=')); fgets(s,sizeof(s)-4,f); /* skip trailing blank line */ } if (verify) if (!quietVerify) printf("\n"); return f; } /* +***************************************************************************** * * Function Name: AES_PutTestResult * * Function: Output a test result * * Arguments: f = output file * name = name of field * p = pointer to bytes/dwords * cnt = # bytes to output * fmt32 = nonzero --> p points to dwords, else bytes * Return: None. * * Notes: * -****************************************************************************/ void AES_PutBytes(FILE *f,CONST char *name,CONST void *p,int cnt,int fmt32) { char s[128]; int i,j,a; if (p == NULL) return; a = (fmt32) ? ADDR_XOR : 0; /* handle big/little endian on dword i/o */ sprintf(s,"%s=",name); for (j=0;s[j];j++) ; for (i=0;i > 4 ]; s[j++]=hexTab[((BYTE *)p)[i ^ a] & 0xF]; } s[j++]='\n'; s[j ]=0; /* terminate the string */ AES_FileIO(f,s,0); } /* +***************************************************************************** * * Function Name: AES_printf * * Function: Output a test result * * Arguments: t = testData (includes output file) * fmt = format list (string of chars, see notes) * * Return: None. * * Notes: * The fmt string specifies what is output. The following characters are * treated specially (S,K,P,C,v,V,I). See the code in the switch statement * to see how they are handled. All other characters (e.g., '\n') are * simply output to the file. * -****************************************************************************/ void AES_printf(testData *t,CONST char *fmt) { char s[40]; for (s[1]=0;*fmt;fmt++) switch (*fmt) { case 'I': sprintf(s,"I=%d\n",t->I); AES_FileIO(t->f,s,0); break; case 'S': sprintf(s,"KEYSIZE=%d\n",t->keySize); AES_FileIO(t->f,s,0); break; case 'P': AES_PutBytes(t->f,"PT" ,t->pt ,BLOCK_SIZE/8,0); break; case 'C': AES_PutBytes(t->f,"CT" ,t->ct ,BLOCK_SIZE/8,0); break; case 'v': AES_PutBytes(t->f,"IV" ,t->ci.IV ,BLOCK_SIZE/8,0); break; case 'V': AES_PutBytes(t->f,"IV" ,t->ci.iv32 ,BLOCK_SIZE/8,1); break; case 'K': AES_PutBytes(t->f,"KEY",t->ki.key32,t->keySize/8,1); break; default: s[0]=*fmt; s[1]=0; AES_FileIO(t->f,s,0); break; } } /* +***************************************************************************** * * Function Name: AES_EndSection * * Function: Insert a separator between sections * * Arguments: t = ptr to testData, contains file * * Return: None. * * Notes: * -****************************************************************************/ void AES_EndSection(testData *t) { AES_FileIO(t->f,"==========\n\n",0); } /* +***************************************************************************** * * Function Name: AES_Close * * Function: Close an AES text file * * Arguments: t = testData ptr (contains f) * * Return: None. * * Notes: * -****************************************************************************/ void AES_Close(testData *t) { fclose(t->f); } /* +***************************************************************************** * * Function Name: DebugIO * * Function: Output debug string * * Arguments: s = string to output * * Return: None. * * Notes: * -****************************************************************************/ void DebugIO(CONST char *s) { if (debugTD) { AES_FileIO(debugTD->f,s,0); debugTD->gotDebugIO=1; } else printf(s); } /* +***************************************************************************** * * Function Name: AES_Test_VK * * Function: Run variable key test * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_VK(CONST char *fname) { testData t; memset(t.ki.keyMaterial,'0',MAX_KEY_SIZE); t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode\nVariable Key Known Answer Tests"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS) { ClearTestData(&t); AES_printf(&t,"S\nP\n"); /* output key size, plaintext */ for (t.I=1;t.I<=t.keySize;t.I++) { t.ki.keyMaterial[(t.I-1)/4]='0' + (8 >> ((t.I-1) & 3)); if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); if (blockEncrypt(&t.ci,&t.ki,t.pt,BLOCK_SIZE,t.ct) != BLOCK_SIZE) FatalError("blockEncrypt return during %s test",fname); AES_printf(&t,"IKC\n"); /* output I, KEY, CT, newline */ t.ki.keyMaterial[(t.I-1)/4]='0'; /* rezero the key bit */ } AES_EndSection(&t); } AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_Intermediate * * Function: Run intermediate value test * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_Intermediate(CONST char *fname) { testData t; if ((useAsm) || (!debugCompile)) { if (!quietVerify) printf("WARNING: Skipping %s test\n",fname); return; } memset(t.ki.keyMaterial,'0',MAX_KEY_SIZE); t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode\nIntermediate Value Tests"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS) { ClearTestData(&t); debugTD=&t; debug=1; if (t.keySize > KEY_BITS_0) memcpy(t.ki.keyMaterial,hexString,sizeof(t.ki.keyMaterial)); debug=0; if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); debug=1; AES_printf(&t,"S\nK\n"); /* output key size, key */ if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); AES_printf(&t,"P\n"); /* output plaintext */ AES_FileIO(t.f,"Encrypt()\n",0); if (blockEncrypt(&t.ci,&t.ki,t.pt,BLOCK_SIZE,t.ct) != BLOCK_SIZE) FatalError("blockEncrypt return during %s test",fname); AES_printf(&t,"\nC\n"); /* output CT, newline */ AES_FileIO(t.f,"Decrypt()\n",0); AES_printf(&t,"\nC\n"); /* output CT, newline */ if (blockDecrypt(&t.ci,&t.ki,t.ct,BLOCK_SIZE,t.pt) != BLOCK_SIZE) FatalError("blockDecrypt return during %s test",fname); AES_printf(&t,"\nP\n"); /* output PT, newline */ AES_EndSection(&t); if (!t.gotDebugIO) FatalError("Need to run DEBUG version to test %s",fname); debug=0; debugTD=NULL; } AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_VT * * Function: Run variable text test * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_VT(CONST char *fname) { testData t; memset( t.ki.keyMaterial,'0',MAX_KEY_SIZE); t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode\nVariable Text Known Answer Tests"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS) { ClearTestData(&t); if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); AES_printf(&t,"S\nK\n"); /* output key size, key */ for (t.I=1;t.I<=BLOCK_SIZE;t.I++) { t.pt[(t.I-1)/8] = 0x80 >> ((t.I-1) & 7); if (blockEncrypt(&t.ci,&t.ki,t.pt,BLOCK_SIZE,t.ct) != BLOCK_SIZE) FatalError("blockEncrypt return during %s test",fname); AES_printf(&t,"IPC\n"); /* output I, PT, CT, newline */ t.pt[(t.I-1)/8] = 0; } AES_EndSection(&t); } AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_TBL * * Function: Run tabl test * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_TBL(CONST char *fname) { int i; testData t; t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode\nTables Known Answer Test\n" "Tests permutation tables and MDS matrix multiply tables."); for (t.keySize=KEY_BITS_0;t.keySize <= MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS) { AES_printf(&t,"S\n"); /* output key size */ TableOp(TAB_ENABLE); TableOp(TAB_RESET); ClearTestData(&t); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("Error cipherInit() during %s test",fname); for (t.I=1;TableOp(TAB_QUERY) == FALSE;t.I++) { if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); if (blockEncrypt(&t.ci,&t.ki,t.pt,BLOCK_SIZE,t.ct) != BLOCK_SIZE) FatalError("blockEncrypt during %s test",fname); AES_printf(&t,"IKPC\n"); /* show the 'vector' */ memcpy(t.ki.keyMaterial+MAX_KEY_SIZE/2,t.ki.keyMaterial,MAX_KEY_SIZE/2); for (i=0;i > 4]; t.ki.keyMaterial[i+1]=hexTab[t.pt[i/2] &0xF]; } memcpy(t.pt,t.ct,BLOCK_SIZE/8); /* use ciphertext as new plaintext */ } TableOp(TAB_DISABLE); AES_EndSection(&t); /* output separator */ if (!quietVerify) printf(" [%d,%3d]",t.keySize,t.I); } if (!quietVerify) printf("\n"); AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_ECB_E_MCT * * Function: Run ECB Monte Carlo test for ECB encryption * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_ECB_E_MCT(CONST char *fname) { int i,j,q; testData t; t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode - ENCRYPTION\nMonte Carlo Test"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0,q=0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS,q+=2) { AES_printf(&t,"S\n"); /* output key size */ if (!quietVerify) printf(" keyLen = %3d. ",t.keySize); ClearTestData(&t); /* start with all zeroes */ if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); for (t.I=0;t.I =q) ? ((DWORD *)t.ct)[i-q] : ((DWORD *)t.pt)[BLOCK_SIZE/32-q+i]); BlockCopy(t.pt,t.ct); } AES_printf(&t,"C\n"); if (reKey(&t.ki) != TRUE) FatalError("reKey return during %s test",fname); } AES_EndSection(&t); } if (!quietVerify) printf(" \n"); AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_ECB_D_MCT * * Function: Run ECB Monte Carlo test for ECB decryption * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_ECB_D_MCT(CONST char *fname) { int i,j,q; testData t; t.f=AES_PutFileHeader(fname, "Electronic Codebook (ECB) Mode - DECRYPTION\nMonte Carlo Test"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0,q=0;t.keySize <= MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS,q+=2) { AES_printf(&t,"S\n"); /* output key size */ if (!quietVerify) printf(" keyLen = %3d. ",t.keySize); ClearTestData(&t); /* start with all zeroes */ if (makeKey(&t.ki,DIR_DECRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); for (t.I=0;t.I =q) ? ((DWORD *)t.pt)[i-q] : ((DWORD *)t.ct)[BLOCK_SIZE/32-q+i]); BlockCopy(t.ct,t.pt); } AES_printf(&t,"P\n"); if (reKey(&t.ki) != TRUE) FatalError("reKey return during %s test",fname); } AES_EndSection(&t); } if (!quietVerify) printf(" \n"); AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_CBC_E_MCT * * Function: Run ECB Monte Carlo test for CBC encryption * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_CBC_E_MCT(CONST char *fname) { int i,j,q; testData t; BYTE ctPrev[BLOCK_SIZE/8]; BYTE IV[BLOCK_SIZE/8]; #define CV t.ci.IV /* use t.ci.IV as CV */ t.f=AES_PutFileHeader(fname, "Cipher Block Chaining (CBC) Mode - ENCRYPTION\nMonte Carlo Test"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0,q=0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS,q+=2) { AES_printf(&t,"S\n"); /* output key size */ if (!quietVerify) printf(" keyLen = %3d. ",t.keySize); ClearTestData(&t); /* start with all zeroes */ memset(IV,0,sizeof(IV)); if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); BlockCopy(CV,IV); for (t.I=0;t.I =q) ? ((DWORD *)t.ct )[i-q] : ((DWORD *)ctPrev)[BLOCK_SIZE/32-q+i]); BlockCopy(t.pt,ctPrev); BlockCopy(CV,t.ct); if (reKey(&t.ki) != TRUE) FatalError("reKey return during %s test",fname); } AES_EndSection(&t); } if (!quietVerify) printf(" \n"); AES_Close(&t); } /* +***************************************************************************** * * Function Name: AES_Test_CBC_D_MCT * * Function: Run ECB Monte Carlo test for CBC decryption * * Arguments: fname = file name to produce * * Return: None. * * Notes: * -****************************************************************************/ void AES_Test_CBC_D_MCT(CONST char *fname) { int i,j,q; testData t; BYTE ptPrev[BLOCK_SIZE/8]; BYTE IV[BLOCK_SIZE/8]; #define CV t.ci.IV /* use t.ci.IV as CV */ t.f=AES_PutFileHeader(fname, "Cipher Block Chaining (CBC) Mode - DECRYPTION\nMonte Carlo Test"); if (cipherInit(&t.ci,MODE_ECB,NULL) != TRUE) FatalError("cipherInit error during %s test",fname); for (t.keySize=KEY_BITS_0,q=0;t.keySize <= MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS,q+=2) { AES_printf(&t,"S\n"); /* output key size */ if (!quietVerify) printf(" keyLen = %3d. ",t.keySize); ClearTestData(&t); /* start with all zeroes */ memset(IV,0,sizeof(IV)); if (makeKey(&t.ki,DIR_DECRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during %s test",fname); BlockCopy(CV,IV); for (t.I=0;t.I =q) ? ((DWORD *)t.pt )[i-q] : ((DWORD *)ptPrev)[BLOCK_SIZE/32-q+i]); if (reKey(&t.ki) != TRUE) FatalError("reKey return during %s test",fname); } AES_EndSection(&t); } if (!quietVerify) printf(" \n"); AES_Close(&t); } /* +***************************************************************************** * * Function Name: ShowParams * * Function: Print out the settings of settable parameters * * Arguments: None. * * Return: None. * * Notes: * -****************************************************************************/ void ShowParams(void) { int saveDebug=debug; testData t; debug=0; /* turn off debug output */ memset(t.ki.keyMaterial,'0',sizeof(t.ki.keyMaterial)); printf("(keyLen,numRounds): "); for (t.keySize=KEY_BITS_0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS) { if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE) FatalError("Error parsing key during ShowParam",""); printf(" (%d,%d)",t.keySize,t.ki.numRounds); } printf("\n"); debug=saveDebug; } /* +***************************************************************************** * * Function Name: ParseArgFile * * Function: Parse commands from argument file * * Arguments: fName = name of file to read * argList = list of ptrs to fill in * maxArgCnt = size of argList * * Return: None. * * Notes: '/' and ';' are comment to end of line characters in the file * This function is used to allow a "custom" set of switches to * be automatically read from a file at startup. * -****************************************************************************/ int ParseArgFile(CONST char *fName,char *argList[],int maxArgCnt) { static char buf[1024]; static int bufCnt=0; /* current # chars in buf */ int i,j,k,argCnt; char line[256]; FILE *f=fopen(fName,"rt"); if (f == NULL) return 0; if (debug) printf("Reading args from file %s: ",fName); for (argCnt=0;argCnt ' ') break; if (line[j]==0) break; for (k=j;line[k];k++) if (line[k] <= ' ') break; /* now j..k-1 defines a token */ if (k-j+1 > (int)(sizeof(buf) - bufCnt)) FatalError("Arg file too large: %s",line); if (argCnt >= maxArgCnt) break; memcpy(buf+bufCnt,line+j,k-j); buf[bufCnt+k-j]=0; /* terminate the token */ if (debug) printf(" %s",buf+bufCnt); argList[argCnt++]=buf+bufCnt; bufCnt+=k-j+1; i=k; /* skip to next token */ } } fclose(f); if (debug) printf("\n"); return argCnt; } /* +***************************************************************************** * * Function Name: GiveHelp * * Function: Print out list of command line switches * * Arguments: None. * * Return: None. * * Notes: * -****************************************************************************/ void GiveHelp(void) { printf("Syntax: TST2FISH [options]\n" "Purpose: Generate/validate AES Twofish code and files\n" "Options: -lNN ==> set sanity check loop to NN\n" " -m ==> do full MCT generation\n" " -pPath ==> set file path\n" " -s ==> set initial random seed based on time\n" " -sNN ==> set initial random seed to NN\n" " -tNN ==> time performance using NN iterations\n" " -v ==> validate files, don't generate them\n", MAX_ROUNDS ); exit(1); } #ifdef TEST_EXTERN void Test_Extern(void); #endif void ShowHex(FILE *f,CONST void *p,int bCnt,CONST char *name) { int i; fprintf(f," ;%s:",name); for (i=0;i