📄 testphelix.c
字号:
/*
****************************************************************
* Make sure the code functions properly
****************************************************************
*/
void PhelixValidityCheck(u32b checkCnt,u32b compareKATcnt)
{
enum { MAX_BYTES=256 };
u32b i,j,k,n,res,aadLen,macSize,keySize,nonceSize,errBit,KATcnt;
u08b key[PHELIX_KEY_SIZE/8],nonce[PHELIX_NONCE_SIZE/8],
mac[2][PHELIX_MAC_SIZE/8],
pText[MAX_BYTES+4],cText[MAX_BYTES+4],dText[MAX_BYTES+4],
aad [MAX_BYTES+4],tmp[3][MAX_BYTES+4];
u08b b;
u08b * macPtr;
refStr lName;
TestVector v;
PhelixContext ctx;
if (checkCnt == 0) return;
/* finally, make sure that the KAT vectors match */
for (k=0;k < compareKATcnt;k++)
{
v = KAT[k];
if (0 == (v.keySize | v.msgLen | v.aadLen | v.macSize | v.nonceSize))
break; /* end of list? */
memset(&ctx,0,sizeof(ctx)); /* for debug i/o cosmetics */
memset(cText,0,v.msgLen);
memset(mac[0],0,v.macSize/8);
PhelixSetupKey (&ctx,v.key,v.keySize,v.nonceSize,v.macSize);
PhelixEncryptPacket(PPv,v.pText,cText,v.msgLen,mac[0]);
if (memcmp(cText,v.cText,v.msgLen))
FatalError("KAT data miscompare on vector #%d",k+1);
if (memcmp(mac ,v.mac ,(v.macSize+7)/8))
FatalError("KAT MAC miscompare on vector #%d",k+1);
}
KATcnt = k;
if (compareKATcnt && compareKATcnt < (sizeof(KAT)/sizeof(KAT[0])) && _debugPhelix_)
exit(0); /* just output some debug info and stop */
/* first perform repeated, random self-consistency checks */
for (j=0;j<checkCnt;j++)
{
RandFill(pText,sizeof(pText));
RandFill(aad ,sizeof(aad) );
RandFill(nonce,sizeof(nonce));
RandFill(key ,sizeof(key) );
memcpy(tmp[2],aad,sizeof(aad)); /* save copy of AAD to make sure it's unchanged */
aadLen = ((j < checkCnt/2) ? j : Rand32()) % MAX_BYTES;
macSize= (j < checkCnt/2) ? PHELIX_MAC_SIZE : RandMacSize(1);
keySize= (j < checkCnt/2) ? PHELIX_KEY_SIZE : RandKeySize(8);
nonceSize=(j < checkCnt/2) ? PHELIX_NONCE_SIZE : RandNonceSize(1);
PhelixSetupKey(&ctx,key,keySize,nonceSize,macSize);
for (n=1;n<MAX_BYTES;n++)
{
b = Rand08();
memset(dText,b,sizeof(dText)); /* fill with known data */
memset(cText,b,sizeof(cText));
memset(mac ,0,sizeof(mac ));
for (k=0;;k++)
{
#ifdef MIX_ASM
if (k && (Rand32() & 1)) /* intermix the C and ASM keying versions */
{
if (Rand32() & 1)
PhelixSetupKey_ASM(&ctx,key,keySize,nonceSize,macSize);
else
PhelixSetupKey (&ctx,key,keySize,nonceSize,macSize);
}
#endif
lName = MethodName(k); /* name of the implementation method */
if (lName == NULL) break; /* stop when out of algorithms */
macPtr = mac[(k) ? 1 : 0];
memcpy(tmp,pText,n);
res = ProcessPacket(k,0,PP_,pText,cText,n,macPtr);
if (res)
FatalError("Encrypt_%s returned an error! [n=%d]",lName,n);
if (memcmp(tmp,pText,n))
FatalError("Encrypt_%s modified the plaintext [n=%d]",lName,n);
if (aadLen && memcmp(tmp[2],aad,aadLen))
FatalError("Encrypt_%s modified AAD [n=%d]",lName,n);
for (i=n;i<sizeof(cText);i++)
if (((u08b *)cText)[i] != b)
FatalError("Encrypt_%s modified extra dest bytes [n=%d]",lName,n);
if (k==0)
memcpy(tmp[1],cText,n); /* save as reference for later comparison */
else
{
if (memcmp(tmp[1],cText,n))
FatalError("Ciphertext miscompare: %s vs. %s [n=%d]",MethodName(0),lName,n);
if (memcmp(mac[0],macPtr,(macSize+7)/8))
FatalError("MAC miscompare: %s vs. %s [n=%d]",MethodName(0),lName,n);
}
memcpy(tmp[0],cText,n);
res=ProcessPacket(k,1,PP_,cText,dText,n,macPtr);
for (i=n;i<sizeof(dText);i++)
if (((u08b *)dText)[i] != b)
FatalError("Decrypt_%s modified extra dest bytes [n=%d]",lName,n);
if (memcmp(tmp[0],cText,n))
FatalError("Decrypt_%s modified the input ciphertext [n=%d]",lName,n);
if (aadLen && memcmp(tmp[2],aad,aadLen))
FatalError("Decrypt_%s modified AAD [n=%d]",lName,n);
if (memcmp(pText,dText,n))
FatalError("Decrypt_%s miscompare [n=%d]",lName,n);
if (res)
FatalError("Decrypt_%s generated a false MAC miscompare [n=%d]",lName,n);
/* force a decrypt MAC error and make sure it gets detected */
memcpy(tmp[0],macPtr,PHELIX_MAC_SIZE/8);
errBit = Rand32() % macSize;
tmp[0][errBit/8] ^= 1 << (errBit % 8); /* inject a bit error */
res=ProcessPacket(k,1,PP_,cText,dText,n,tmp[0]);
if (res == 0)
FatalError("Decrypt_%s missed a MAC miscompare [n=%d]",lName,n);
if (macSize < PHELIX_MAC_SIZE)
for (i=0;i<4;i++)
{ /* insert decrypt MAC error just after the limit to make sure it's ignored */
memcpy(tmp[0],macPtr,PHELIX_MAC_SIZE/8);
errBit = macSize + ((i) ? (Rand32() % (PHELIX_MAC_SIZE-macSize)) : 0);
tmp[0][errBit/8] ^= 1 << (errBit % 8); /* inject a bit error */
res=ProcessPacket(k,1,PP_,cText,dText,n,tmp[0]);
if (res != 0)
FatalError("Decrypt_%s found false truncated MAC miscompare [n=%d]",lName,n);
}
/* test encrypt and decrypt "in place" */
memcpy(dText,cText,n);
res=ProcessPacket(k,1,PP_,dText,dText,n,macPtr);
if (res) FatalError("Decrypt_%s in-place failed (%d)\n",lName,n);
if (memcmp(dText,pText,n))
FatalError("Decrypt_%s in-place miscompare (%d)\n",lName,n);
res=ProcessPacket(k,0,PP_,dText,dText,n,tmp[0]);
if (res) FatalError("Encrypt_%s in-place failed (%d)\n",lName,n);
if (memcmp(dText,cText,n))
FatalError("Encrypt_%s in-place miscompare (%d)\n",lName,n);
}
}
}
printf("ValidityCheck OK: %s [%d KAT vectors]\n",PHELIX_CIPHER_NAME,KATcnt);
}
/*
****************************************************************
* Test the speed of various algorithm implementations
****************************************************************
*/
void PhelixPerfTest(u32b callCnt)
{
enum { TEST_CNT=8, MAX_FUNC=5, MAX_BYTES=1024 };
refStr TEST_NAME[MAX_FUNC]=
{"Encrypt:","Decrypt:","Encrypt_inc:","Decrypt_inc:","KeySetup:"};
refStr SHOW_EQN = "YYYYn";
u32b i,j,k,n,N,a,t0,t1,p,codeSize;
u32b dt[TEST_CNT+1],dtMin,dtMax,dtSum;
u08b key[PHELIX_KEY_SIZE/8],nonce[PHELIX_NONCE_SIZE/8],
mac[PHELIX_MAC_SIZE/8],pText[MAX_BYTES+4],cText[MAX_BYTES+4];
struct { u32b n,dt; } pts[8];
double denom;
PhelixContext ctx;
if (callCnt == 0) return;
RandFill(pText,sizeof(pText));
RandFill(key ,sizeof(key));
RandFill(nonce,sizeof(nonce));
dtMin = 0; /* avoid MSVC compiler warning: uninitialized */
if (_timeAADcnt_)
printf("AAD cnt = %d bytes\n",_timeAADcnt_);
printf("****** Performance of Phelix functions compiled by '%s' ******\n",PhelixCompiler_Name());
printf(" Code Size| Packet Size (N) | Clk equation\n");
printf("Method (bytes)|");
for (n=64;n<=MAX_BYTES;n*=4)
printf("%6d bytes",n);
printf(" | (approx)\n");
printf( "----------------------|-------------------------------------|--------------------\n");
for (k=0;k < MAX_FUNC;k++)
{
switch (k)
{
case 0:
case 1: codeSize = PhelixProcessPacket_CodeSize(); break;
case 2:
case 3: codeSize = PhelixIncremental_CodeSize(); break;
default:codeSize = 0; break;
}
printf("%-16s",TEST_NAME[k]);
if (SHOW_EQN[k] == 'Y')
printf((codeSize)?"%5d |":" |",codeSize);
PhelixSetupKey(&ctx,key,PHELIX_KEY_SIZE,PHELIX_NONCE_SIZE,PHELIX_MAC_SIZE);
for (n=64,p=0;n<=MAX_BYTES;n*=4,p++)
{
a = (n < _timeAADcnt_) ? n : _timeAADcnt_;
N = n - a;
for (j=0;j<TEST_CNT;j++)
{
t0=HighFreqCounter();
switch (k)
{
case 0:
for (i=0;i<callCnt;i++)
PhelixEncryptPacket(&ctx,nonce,pText,a,pText+a,cText,N,mac);
break;
case 1:
for (i=0;i<callCnt;i++)
PhelixEncryptPacket(&ctx,nonce,pText,a,cText,pText,N,mac);
break;
case 2:
for (i=0;i<callCnt;i++)
{
PhelixSetupNonce (&ctx,nonce);
if (a)
PhelixProcessAAD(&ctx,pText,a);
PhelixEncryptBytes(&ctx,pText+a,cText,N);
PhelixFinalize (&ctx,mac);
}
break;
case 3:
for (i=0;i<callCnt;i++)
{
PhelixSetupNonce (&ctx,nonce);
if (a)
PhelixProcessAAD(&ctx,pText,a);
PhelixDecryptBytes(&ctx,pText+a,cText,N);
PhelixFinalize (&ctx,mac);
}
break;
case 4:
for (i=0;i<callCnt;i++)
PhelixSetupKey(&ctx,key,PHELIX_KEY_SIZE,PHELIX_NONCE_SIZE,PHELIX_MAC_SIZE);
break;
}
t1=HighFreqCounter();
dt[j]=t1-t0;
}
/* show timing results */
if (_verbose_)
printf(" dt for %d calls (%d bytes each):\n",callCnt,n);
for (i=0,dtMax=dtSum=0,dtMin=~0u;i<TEST_CNT;i++)
{
if (_verbose_) printf("%9d",dt[i]);
if (dtMin > dt[i]) dtMin=dt[i];
if (dtMax < dt[i]) dtMax=dt[i];
dtSum+=dt[i];
}
if (_verbose_)
printf("\nClocks per call = %d [min]\n",dtMin/callCnt);
if (SHOW_EQN[k] != 'Y')
{
printf("%15d clocks",dtMin/callCnt);
break;
}
denom = (double) (callCnt*n);
printf("%8.2f cpb",dtMin/denom);
pts[p].n = n;
pts[p].dt = dtMin;
if (_verbose_)
printf(", %5.2f [discard], %5.2f [all]",
(dtSum-dtMin-dtMax)/((TEST_CNT-2)*denom),dtSum/(TEST_CNT*denom));
}
if (p > 1) /* need two points to define an equation */
{ /* could do least squares, but it's not worth it */
assert(pts[p-1].n > pts[p-2].n);
denom = callCnt * (double)(pts[p-1].n - pts[p-2].n);
printf(" |%6.0f +%6.2f * N",
(pts[p-1].n*pts[p-2].dt-pts[p-2].n*dtMin)/denom,
(dtMin-pts[p-2].dt)/denom);
}
printf("\n");
}
}
/* display a help message on command-line options and then exit */
void GiveHelp(void)
{
printf
(
"Syntax: testPhelix [option]*\n"
"Purpose: Test Phelix functionality and performance\n"
"Options: -A = measure AAD speed\n"
" -D = output debug info\n"
" -F = do not validate functionality\n"
" -Fn = run n validation loops\n"
" -G = generate KAT vectors and exit\n"
" -K = do not compare C to KAT vectors\n"
" -Sn = set initial random seed to n\n"
" -Tn = measure performance over n calls\n"
" -V = verbose mode\n"
" -3 = allow debugger traps\n"
);
exit(2);
}
int main(int argc,char *argv[])
{
int i;
refStr genKAT = NULL;
u32b funcTestCnt = 64;
u32b compareKATcnt = KAT_CNT; /* default is all of KAT vectors */
u32b perfCallCnt = (DO_PERF_TEST) ? 16 : 0;
u32b randSeed = time(NULL);
char compilerName[128];
time_t t;
#ifdef CompilerMajorVersion
sprintf(compilerName,CompilerID,CompilerMajorVersion,CompilerMinorVersion);
#else
sprintf(compilerName,"%s",CompilerID);
#endif
time(&t);
for (i=1;i<argc;i++)
{
if (argv[i][0] == '-' || argv[i][0] == '/')
switch(toupper(argv[i][1]))
{
case '?': GiveHelp(); break;
case '3': _allowTrap_ = 1; break;
case 'A': _timeAADcnt_ = atoi(argv[i]+2); break;
case 'D': _debugPhelix_ = 1; break;
case 'F': funcTestCnt = atoi(argv[i]+2); break;
case 'G': genKAT = argv[i]+2; break;
case 'K': compareKATcnt = atoi(argv[i]+2); break;
case 'S': randSeed = atoi(argv[i]+2); break;
case 'T': perfCallCnt = atoi(argv[i]+2); break;
case 'V': _verbose_ = 1; break;
default: FatalError("Unknown switch",argv[i]); break;
}
else if (argv[i][0] == '?')
GiveHelp();
}
RandReseed(randSeed);
if (genKAT)
{
GenerateKAT(genKAT); /* just output the vectors and return */
return 0; /* (i.e., can redirect output directly to PhelixKAT.h :-) */
}
ShowCPUinfo(); /* find out the CPU type and speed */
printf("Test compiled by %s%s, %s %s.\nrandSeed=%d. callCnt = %d. Run @ %s",
compilerName,CompilerMode,__DATE__,__TIME__,randSeed,perfCallCnt,ctime(&t));
#ifdef MIX_ASM
printf("Randomly inter-mixing C and assembly calls\n");
#endif
/* run the one-time init function */
PhelixInit();
/* make sure the code functions properly */
PhelixValidityCheck(funcTestCnt,compareKATcnt);
/* time the code to see how fast it is */
PhelixPerfTest(perfCallCnt);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -