📄 tst2fish.c
字号:
printf(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n");
}
/*
+*****************************************************************************
*
* Function Name: AES_Sanity_Check
*
* Function: Make sure things work to the interface spec and
* that encryption and decryption are inverse functions
*
* Arguments: None.
*
* Return: None.
*
* Notes: Will FatalError if any problems found
*
-****************************************************************************/
void AES_Sanity_Check(int testCnt)
{
static DWORD hexVal[] =
{0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,
0x33221100,0x77665544,0xBBAA9988,0xFFEEDDCC};
static char *modeNames[]={"(null)","MODE_ECB","MODE_CBC","MODE_CFB1"};
int i,j,q,n,testNum,lim,saveDebug=debug;
testData t;
keyInstance k2;
BYTE pt[128];
BYTE ct[128];
char ivString[BLOCK_SIZE/4];
char *mName;
BYTE mode;
#if ALIGN32
BYTE alignDummy[3]; /* keep dword alignment on stack after BYTE mode */
#endif
if (!quietVerify) printf("\nTwofish code sanity check...");
#if (MODE_CFB1 != MODE_ECB + 2)
#error Need to change mode loop constants
#endif
if (testCnt)
for (mode=MODE_ECB;mode<=MODE_CFB1;mode++)
{
debug=(mode == saveDebug);
mName=modeNames[mode];
if (cipherInit(&t.ci,mode,hexString) != TRUE)
FatalError("cipherInit error during sanity check %s",mName);
if (t.ci.mode != mode)
FatalError("Cipher mode not set properly during sanity check %s",mName);
if (mode != MODE_ECB)
for (i=0;i<BLOCK_SIZE/32;i++)
if (t.ci.iv32[i] != hexVal[i])
FatalError("Invalid IV parse during sanity check %s",mName);
lim = (mode == MODE_CFB1) ? (testCnt+31)/32 : testCnt;
for (t.keySize=KEY_BITS_0;t.keySize <= MAX_KEY_BITS;t.keySize+=STEP_KEY_BITS)
{
/* printf("Running %-9s sanity check on keySize = %3d.\n",mName,t.keySize); */
if (!quietVerify) printf("."); /* show some progress */
ClearTestData(&t);
debug=0; /* don't show debug info in this makeKey call */
if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,hexString) != TRUE)
FatalError("Error parsing key during sanity check %s",mName);
debug=(mode == saveDebug);
for (i=0;i<t.keySize/32;i++)
if (t.ki.key32[i]!=hexVal[i])
FatalError("Invalid key parse during sanity check %s",mName);
for (testNum=0;testNum<lim;testNum++)
{ /* run a bunch of encode/decode tests */
if ((testNum&0x1F)==0) /* periodic re-key time? */
{
for (j=0;j<t.keySize/4;j++)
t.ki.keyMaterial[j]=hexTab[Rand() & 0xF];
if (testNum==0)
ClearTestData(&t); /* give "easy" test data the first time */
if (makeKey(&t.ki,DIR_ENCRYPT,t.keySize,t.ki.keyMaterial) != TRUE)
FatalError("Encrypt makeKey during sanity check %s",mName);
debug=0;
if (makeKey(&k2 ,DIR_DECRYPT,t.keySize,t.ki.keyMaterial) != TRUE)
FatalError("Decrypt makeKey during sanity check %s",mName);
debug=(mode == saveDebug);
}
if (mode != MODE_ECB) /* set IV if needed*/
for (j=0;j<BLOCK_SIZE/4;j++)
ivString[j]=hexTab[(testNum)? Rand() & 0xF : 0];
if ((debug) || (testNum == 0))
n = (BLOCK_SIZE/8); /* do only one block if debugging */
else
n = (BLOCK_SIZE/8)*(1 + (Rand() % (sizeof(pt)/(BLOCK_SIZE/8))));
for (j=0;j<n;j++) /* set random plaintext */
pt[j]=(testNum) ? (BYTE) Rand() : 0;
if (mode == MODE_CBC)
{ /* check that CBC works as advertised */
cipherInit(&t.ci,mode,ivString);
t.ci.mode=MODE_ECB;
for (q=0;q<BLOCK_SIZE/8;q++) /* copy over the iv */
t.pt[q] = (BYTE) (t.ci.iv32[q/4] >> (8*(q&3))); /* auto-Bswap! */
for (j=0;j<n;j+=BLOCK_SIZE/8)
{
for (q=0;q<BLOCK_SIZE/8;q++) /* xor in next block */
t.pt[q] ^= pt[j+q];
debug=0;
if (BLOCK_SIZE != blockEncrypt(&t.ci,&t.ki,t.pt,BLOCK_SIZE,t.pt))
FatalError("blockEncrypt return value during sanity check %s",mName);
debug=(mode == saveDebug);
}
t.ci.mode=MODE_CBC; /* restore mode */
}
/* encrypt */
cipherInit(&t.ci,mode,ivString);
if (n*8 != blockEncrypt(&t.ci,&t.ki,pt,n*8,ct))
FatalError("blockEncrypt return value during sanity check %s",mName);
if (mode == MODE_CBC) /* validate CBC "hash" */
for (q=0;q<BLOCK_SIZE/8;q++)
if (t.pt[q] != ct[n-BLOCK_SIZE/8+q])
FatalError("CBC doesn't work during sanity check %s",mName);
/* decrypt */
cipherInit(&t.ci,mode,ivString);
if (n*8 != blockDecrypt(&t.ci,&t.ki,ct,n*8,ct))
FatalError("blockDecrypt return value during sanity check %s",mName);
/* compare */
for (j=0;j<n;j++)
if (pt[j] != ct[j])
{
char s[128];
sprintf(s,"Sanity check: encrypt/decrypt miscompare (mode=%s,keySize=%d)",
mName,t.keySize);
FatalError(s,"");
}
if (debug)
{
if (testNum >= 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<cnt;i++)
{
s[j++]=hexTab[((BYTE *)p)[i ^ a] >> 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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -