📄 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
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<TEST_CNT;i++)
{
if (needSet[i] & 1)
{
denom[i]=sizeof(text)/((CLKS_BYTE) ? 1 : (BLOCK_SIZE/8) );
atomName[i] = (CLKS_BYTE) ? "byte " : "block";
}
format [i] = (CLKS_BYTE) ? "%10.1f/%s " : "%10.0f/%s ";
}
for (i=0;i<MAX_KEY_SIZE;i++) /* generate random key material */
t.ki.keyMaterial[i]=hexTab[Rand() & 0xF];
for (j=0;j<sizeof(text);j++)
text[j]=(BYTE) Rand();
memset(dt,0,sizeof(dt));
dt[0]++; /* make sure it's in the cache */
/* calibrate our timing code */
t0=GetTimer(); t1=GetTimer(); t0++; t1++; /* force cache line fill */
for (i=0;i<sizeof(dt)/sizeof(dt[0]);i++)
{
t0=GetTimer();
t1=GetTimer();
dt[i]=t1-t0;
}
for (n=0;n<TEST_CNT;n++) /* gather all data into testTime[][] */
{
for (t.keySize=KEY_BITS_0,q=0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS,q++)
{
cipherInit(&t.ci,MODE_ECB,NULL);
makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial);
#if defined(HI_RES_CLK)
#define CALL_N /* just call once */
#define ICNT 1.0
#define TSCALE 1.0
for (k=0,minT=~0lu;k<iterCnt;k++)
#else
#define CALL_N for (j=0;j<iterCnt;j++)
#define ICNT ((double)iterCnt)
#define TSCALE ((1.0E6*CLK_MHZ)/CLOCKS_PER_SEC)
for (k=0,minT=~0lu;k<4;k++)
#endif
{ /* run a few times to get "best" time */
switch (n)
{
case 0:
blockEncrypt(&t.ci,&t.ki,text,sizeof(text)*8,text);
GetTimer();
t0=GetTimer();
CALL_N blockEncrypt(&t.ci,&t.ki,text,sizeof(text)*8,text);
t1=GetTimer();
break;
case 1:
blockDecrypt(&t.ci,&t.ki,text,sizeof(text)*8,text);
GetTimer();
t0=GetTimer();
CALL_N blockDecrypt(&t.ci,&t.ki,text,sizeof(text)*8,text);
t1=GetTimer();
break;
case 2:
reKey(&t.ki);
GetTimer();
t0=GetTimer();
CALL_N { t.ki.key32[0]+=0x87654321; /* change key bytes to force cache misses */
t.ki.key32[1]+=0x9ABCDEF3;
reKey(&t.ki); }
t1=GetTimer();
break;
default:
FatalError("Unknown test","");
break;
}
if (minT > 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<sizeof(dt)/sizeof(dt[0]);i++)
printf("%6ld",dt[i]);
printf("\n\n");
}
#else
printf("All times in clks, assuming %d MHz CPU (use -fmNN switch to set)\n",CLK_MHZ);
printf("CLOCKS_PER_SEC = %8.1f\n",(double)CLOCKS_PER_SEC);
#endif
printf("%-13s","keySize=");
for (t.keySize=KEY_BITS_0;t.keySize<=MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS)
printf("%10d bits ",t.keySize);
printf("\n");
for (n=0;n<TEST_CNT;n++)
{
printf("%-13s",testName[n]);
for (q=0;q<3;q++)
{
printf(format[n],TSCALE*testTime[q][n]/(ICNT*(double)denom[n]),atomName[n]);
}
printf("\n");
}
if (FMT_LOG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -