1/* 2 * hashTimeLibCrypt.cpp - measure performance of libcrypt digest ops. 3 * 4 * Thjis is obsolete; hashTime does this a lot better,a dn it also measures raw 5 * CommonCrypto and CryptKit versions. 6 */ 7 8#include <openssl/sha.h> 9#include <openssl/md5.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include "cputime.h" 14#include "cspwrap.h" 15#include "common.h" 16#include "pbkdDigest.h" 17 18/* enumerate digest algorithms our way */ 19typedef int HT_Alg; 20enum { 21 HA_MD5 = 0, 22 HA_SHA1 23}; 24 25#define FIRST_ALG HA_MD5 26#define LAST_ALG HA_SHA1 27 28static void usage(char **argv) 29{ 30 printf("Usage: %s [option ...]\n", argv[0]); 31 printf("Options:\n"); 32 printf(" t=testspec; default=all\n"); 33 printf(" test specs: c digest context setup/teardown\n"); 34 printf(" b basic single block digest\n"); 35 printf(" d digest lots of data\n"); 36 printf(" l=loops (only valid if testspec is given)\n"); 37 exit(1); 38} 39 40/* passed to each test */ 41typedef struct { 42 unsigned loops; 43 bool isSha; 44} TestParams; 45 46/* just digest context setup/teardown */ 47/* returns nonzero on error */ 48static int hashContext( 49 TestParams *params) 50{ 51 unsigned loop; 52 CPUTime startTime; 53 double timeSpentMs; 54 DigestCtx ctx; 55 int rtn; 56 57 startTime = CPUTimeRead(); 58 for(loop=0; loop<params->loops; loop++) { 59 rtn = DigestCtxInit(&ctx, params->isSha); 60 if(!rtn) { 61 return -1; 62 } 63 } 64 timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); 65 66 printf(" context setup/delete : %u ops in %.2f ms; %f ms/op\n", 67 params->loops, timeSpentMs, timeSpentMs / (double)params->loops); 68 return 0; 69} 70 71/* Minimal init/digest/final */ 72#define BASIC_BLOCK_SIZE 64 // to digest in bytes 73#define MAX_DIGEST_SIZE 20 // we provide, no malloc below CSSM 74 75static int hashBasic( 76 TestParams *params) 77{ 78 unsigned loop; 79 CPUTime startTime; 80 double timeSpentMs; 81 uint8 ptext[BASIC_BLOCK_SIZE]; 82 uint8 digest[MAX_DIGEST_SIZE]; 83 DigestCtx ctx; 84 int rtn; 85 86 /* random data, const thru the loops */ 87 appGetRandomBytes(ptext, BASIC_BLOCK_SIZE); 88 89 /* start critical timing loop */ 90 startTime = CPUTimeRead(); 91 for(loop=0; loop<params->loops; loop++) { 92 rtn = DigestCtxInit(&ctx, params->isSha); 93 if(!rtn) { 94 return -1; 95 } 96 rtn = DigestCtxUpdate(&ctx, ptext, BASIC_BLOCK_SIZE); 97 if(!rtn) { 98 return -1; 99 } 100 rtn = DigestCtxFinal(&ctx, digest); 101 if(!rtn) { 102 return -1; 103 } 104 } 105 DigestCtxFree(&ctx); 106 timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); 107 printf(" Digest one %u byte block : %u ops in %.2f ms; %f ms/op\n", 108 BASIC_BLOCK_SIZE, params->loops, 109 timeSpentMs, timeSpentMs / (double)params->loops); 110 return 0; 111} 112 113/* Lots of data */ 114#define PTEXT_SIZE 1000 // to digest in bytes 115#define INNER_LOOPS 1000 116 117static int hashDataRate( 118 TestParams *params) 119{ 120 unsigned loop; 121 unsigned iloop; 122 CPUTime startTime; 123 double timeSpent, timeSpentMs; 124 uint8 ptext[PTEXT_SIZE]; 125 uint8 digest[MAX_DIGEST_SIZE]; 126 DigestCtx ctx; 127 int rtn; 128 129 /* random data, const thru the loops */ 130 appGetRandomBytes(ptext, PTEXT_SIZE); 131 132 /* start critical timing loop */ 133 startTime = CPUTimeRead(); 134 for(loop=0; loop<params->loops; loop++) { 135 rtn = DigestCtxInit(&ctx, params->isSha); 136 if(!rtn) { 137 return -1; 138 } 139 for(iloop=0; iloop<INNER_LOOPS; iloop++) { 140 rtn = DigestCtxUpdate(&ctx, ptext, PTEXT_SIZE); 141 if(!rtn) { 142 return -1; 143 } 144 } 145 rtn = DigestCtxFinal(&ctx, digest); 146 if(!rtn) { 147 return -1; 148 } 149 } 150 timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); 151 timeSpent = timeSpentMs / 1000.0; 152 153 float bytesPerLoop = INNER_LOOPS * PTEXT_SIZE; 154 float totalBytes = params->loops * bytesPerLoop; 155 156 /* careful, KByte = 1024, ms = 1/1000 */ 157 printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", 158 bytesPerLoop, params->loops, 159 timeSpentMs, timeSpentMs / (double)params->loops, 160 ((float)totalBytes / 1024.0) / timeSpent); 161 return 0; 162} 163 164 165typedef int (*testRunFcn)(TestParams *testParams); 166 167/* 168 * Static declaration of a test 169 */ 170typedef struct { 171 const char *testName; 172 unsigned loops; 173 testRunFcn run; 174 char testSpec; // for t=xxx cmd line opt 175} TestDefs; 176 177static TestDefs testDefs[] = 178{ 179 { "Digest context setup/teardown", 180 100000, 181 hashContext, 182 'c', 183 }, 184 { "Basic single block digest", 185 100000, 186 hashBasic, 187 'b', 188 }, 189 { "Large data digest", 190 1000, 191 hashDataRate, 192 'd', 193 }, 194}; 195 196static void algToAlgId( 197 HT_Alg alg, 198 bool *isSha, 199 const char **algStr) 200{ 201 switch(alg) { 202 case HA_MD5: 203 *isSha = false; 204 *algStr = "MD5"; 205 break; 206 case HA_SHA1: 207 *isSha = true; 208 *algStr = "SHA1"; 209 break; 210 default: 211 printf("***algToAlgId screwup\n"); 212 exit(1); 213 } 214} 215 216#define NUM_TESTS (sizeof(testDefs) / sizeof(testDefs[0])) 217 218int main(int argc, char **argv) 219{ 220 TestParams testParams; 221 TestDefs *testDef; 222 int rtn; 223 int arg; 224 char *argp; 225 unsigned cmdLoops = 0; // can be specified in cmd line 226 // if not, use TestDefs.loops 227 char testSpec = '\0'; // allows specification of one test 228 // otherwise run all 229 HT_Alg alg; 230 const char *algStr; 231 232 for(arg=1; arg<argc; arg++) { 233 argp = argv[arg]; 234 switch(argp[0]) { 235 case 't': 236 testSpec = argp[2]; 237 break; 238 case 'l': 239 cmdLoops = atoi(&argp[2]); 240 break; 241 default: 242 usage(argv); 243 } 244 } 245 246 for(unsigned testNum=0; testNum<NUM_TESTS; testNum++) { 247 testDef = &testDefs[testNum]; 248 249 if(testSpec && (testDef->testSpec != testSpec)) { 250 continue; 251 } 252 printf("%s:\n", testDef->testName); 253 if(cmdLoops) { 254 /* user specified */ 255 testParams.loops = cmdLoops; 256 } 257 else { 258 /* default */ 259 testParams.loops = testDef->loops; 260 } 261 for(alg=FIRST_ALG; alg<=LAST_ALG; alg++) { 262 algToAlgId(alg, &testParams.isSha, &algStr); 263 printf(" === %s ===\n", algStr); 264 rtn = testDef->run(&testParams); 265 if(rtn) { 266 printf("Test returned error\n"); 267 exit(1); 268 } 269 } 270 } 271 return 0; 272} 273