X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp b/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp new file mode 100644 index 00000000..f8cfd3b5 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp @@ -0,0 +1,272 @@ +/* + * hashTimeLibCrypt.cpp - measure performance of libcrypt digest ops. + * + * Thjis is obsolete; hashTime does this a lot better,a dn it also measures raw + * CommonCrypto and CryptKit versions. + */ + +#include +#include +#include +#include +#include +#include "cputime.h" +#include "cspwrap.h" +#include "common.h" +#include "pbkdDigest.h" + +/* enumerate digest algorithms our way */ +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); +} + +/* passed to each test */ +typedef struct { + unsigned loops; + bool isSha; +} TestParams; + +/* just digest context setup/teardown */ +/* returns nonzero on error */ +static int hashContext( + TestParams *params) +{ + unsigned loop; + CPUTime startTime; + double timeSpentMs; + DigestCtx ctx; + int rtn; + + startTime = CPUTimeRead(); + for(loop=0; looploops; 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; +} + +/* Minimal init/digest/final */ +#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; + + /* random data, const thru the loops */ + appGetRandomBytes(ptext, BASIC_BLOCK_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; 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; +} + +/* Lots of data */ +#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; + + /* random data, const thru the loops */ + appGetRandomBytes(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + rtn = DigestCtxInit(&ctx, params->isSha); + if(!rtn) { + return -1; + } + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + 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); + +/* + * Static declaration of a test + */ +typedef struct { + const char *testName; + unsigned loops; + testRunFcn run; + char testSpec; // for t=xxx cmd line opt +} 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; // can be specified in cmd line + // if not, use TestDefs.loops + char testSpec = '\0'; // allows specification of one test + // otherwise run all + HT_Alg alg; + const char *algStr; + + for(arg=1; argtestSpec != testSpec)) { + continue; + } + printf("%s:\n", testDef->testName); + if(cmdLoops) { + /* user specified */ + testParams.loops = cmdLoops; + } + else { + /* default */ + 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; +}