hashTimeLibCrypt.cpp [plain text]
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cputime.h"
#include "cspwrap.h"
#include "common.h"
#include "pbkdDigest.h"
typedef int HT_Alg;
enum {
HA_MD5 = 0,
HA_SHA1
};
#define FIRST_ALG HA_MD5
#define LAST_ALG HA_SHA1
static void usage(char **argv)
{
printf("Usage: %s [option ...]\n", argv[0]);
printf("Options:\n");
printf(" t=testspec; default=all\n");
printf(" test specs: c digest context setup/teardown\n");
printf(" b basic single block digest\n");
printf(" d digest lots of data\n");
printf(" l=loops (only valid if testspec is given)\n");
exit(1);
}
typedef struct {
unsigned loops;
bool isSha;
} TestParams;
static int hashContext(
TestParams *params)
{
unsigned loop;
CPUTime startTime;
double timeSpentMs;
DigestCtx ctx;
int rtn;
startTime = CPUTimeRead();
for(loop=0; loop<params->loops; loop++) {
rtn = DigestCtxInit(&ctx, params->isSha);
if(!rtn) {
return -1;
}
}
timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
printf(" context setup/delete : %u ops in %.2f ms; %f ms/op\n",
params->loops, timeSpentMs, timeSpentMs / (double)params->loops);
return 0;
}
#define BASIC_BLOCK_SIZE 64 // to digest in bytes
#define MAX_DIGEST_SIZE 20 // we provide, no malloc below CSSM
static int hashBasic(
TestParams *params)
{
unsigned loop;
CPUTime startTime;
double timeSpentMs;
uint8 ptext[BASIC_BLOCK_SIZE];
uint8 digest[MAX_DIGEST_SIZE];
DigestCtx ctx;
int rtn;
appGetRandomBytes(ptext, BASIC_BLOCK_SIZE);
startTime = CPUTimeRead();
for(loop=0; loop<params->loops; loop++) {
rtn = DigestCtxInit(&ctx, params->isSha);
if(!rtn) {
return -1;
}
rtn = DigestCtxUpdate(&ctx, ptext, BASIC_BLOCK_SIZE);
if(!rtn) {
return -1;
}
rtn = DigestCtxFinal(&ctx, digest);
if(!rtn) {
return -1;
}
}
DigestCtxFree(&ctx);
timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
printf(" Digest one %u byte block : %u ops in %.2f ms; %f ms/op\n",
BASIC_BLOCK_SIZE, params->loops,
timeSpentMs, timeSpentMs / (double)params->loops);
return 0;
}
#define PTEXT_SIZE 1000 // to digest in bytes
#define INNER_LOOPS 1000
static int hashDataRate(
TestParams *params)
{
unsigned loop;
unsigned iloop;
CPUTime startTime;
double timeSpent, timeSpentMs;
uint8 ptext[PTEXT_SIZE];
uint8 digest[MAX_DIGEST_SIZE];
DigestCtx ctx;
int rtn;
appGetRandomBytes(ptext, PTEXT_SIZE);
startTime = CPUTimeRead();
for(loop=0; loop<params->loops; loop++) {
rtn = DigestCtxInit(&ctx, params->isSha);
if(!rtn) {
return -1;
}
for(iloop=0; iloop<INNER_LOOPS; iloop++) {
rtn = DigestCtxUpdate(&ctx, ptext, PTEXT_SIZE);
if(!rtn) {
return -1;
}
}
rtn = DigestCtxFinal(&ctx, digest);
if(!rtn) {
return -1;
}
}
timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
timeSpent = timeSpentMs / 1000.0;
float bytesPerLoop = INNER_LOOPS * PTEXT_SIZE;
float totalBytes = params->loops * bytesPerLoop;
printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n",
bytesPerLoop, params->loops,
timeSpentMs, timeSpentMs / (double)params->loops,
((float)totalBytes / 1024.0) / timeSpent);
return 0;
}
typedef int (*testRunFcn)(TestParams *testParams);
typedef struct {
const char *testName;
unsigned loops;
testRunFcn run;
char testSpec; } TestDefs;
static TestDefs testDefs[] =
{
{ "Digest context setup/teardown",
100000,
hashContext,
'c',
},
{ "Basic single block digest",
100000,
hashBasic,
'b',
},
{ "Large data digest",
1000,
hashDataRate,
'd',
},
};
static void algToAlgId(
HT_Alg alg,
bool *isSha,
const char **algStr)
{
switch(alg) {
case HA_MD5:
*isSha = false;
*algStr = "MD5";
break;
case HA_SHA1:
*isSha = true;
*algStr = "SHA1";
break;
default:
printf("***algToAlgId screwup\n");
exit(1);
}
}
#define NUM_TESTS (sizeof(testDefs) / sizeof(testDefs[0]))
int main(int argc, char **argv)
{
TestParams testParams;
TestDefs *testDef;
int rtn;
int arg;
char *argp;
unsigned cmdLoops = 0; char testSpec = '\0'; HT_Alg alg;
const char *algStr;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 't':
testSpec = argp[2];
break;
case 'l':
cmdLoops = atoi(&argp[2]);
break;
default:
usage(argv);
}
}
for(unsigned testNum=0; testNum<NUM_TESTS; testNum++) {
testDef = &testDefs[testNum];
if(testSpec && (testDef->testSpec != testSpec)) {
continue;
}
printf("%s:\n", testDef->testName);
if(cmdLoops) {
testParams.loops = cmdLoops;
}
else {
testParams.loops = testDef->loops;
}
for(alg=FIRST_ALG; alg<=LAST_ALG; alg++) {
algToAlgId(alg, &testParams.isSha, &algStr);
printf(" === %s ===\n", algStr);
rtn = testDef->run(&testParams);
if(rtn) {
printf("Test returned error\n");
exit(1);
}
}
}
return 0;
}