]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/hashTimeSA/hashTimeSA.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / SecurityTests / cspxutils / hashTimeSA / hashTimeSA.cpp
1 /*
2 * hashTimeSA.cpp - measure performance of digest ops, standalone version (no
3 * dependency on Security.framewortk or on CommonCrypto portion of libSystem).
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <CommonCrypto/CommonDigest.h> /* static lib used in Tiger */
10 #include "MD5.h" /* CryptKit version used in Panther and prior */
11 #include "SHA1.h" /* ditto */
12 #include <Security/cssmtype.h> /* for ALGID values */
13 #include <Security/cssmapple.h> /* more ALGID values */
14 #include <CoreFoundation/CFDate.h>
15
16 /* enumerate digest algorithms our way */
17 typedef int HT_Alg;
18 enum {
19 HA_MD5 = 0,
20 HA_SHA1,
21 HA_SHA224,
22 HA_SHA256,
23 HA_SHA384,
24 HA_SHA512
25 };
26
27 #define FIRST_ALG HA_MD5
28 #define LAST_ALG HA_SHA512
29
30 static void usage(char **argv)
31 {
32 printf("Usage: %s c|k [option ...]\n", argv[0]);
33 printf(" c=CommonCrypto; k=CryptKit\n");
34 printf("Options:\n");
35 printf(" a=alg; default=all\n");
36 printf(" algs: m : MD5\n");
37 printf(" s : SHA1\n");
38 printf(" 4 : SHA224\n");
39 printf(" 2 : SHA256\n");
40 printf(" 3 : SHA384\n");
41 printf(" 5 : SHA512\n");
42 printf(" l=loops (only valid if testspec is given)\n");
43 printf(" v verify digest by printing it\n");
44 exit(1);
45 }
46
47 static void dumpDigest(
48 const unsigned char *digest,
49 unsigned len)
50 {
51 for(unsigned dex=0; dex<len; dex++) {
52 printf("%02X", *digest++);
53 if((dex % 4) == 3) {
54 printf(" ");
55 }
56 }
57 printf("\n");
58 }
59
60 /* sort-of random, but repeatable */
61 static void initPtext(
62 unsigned char *ptext,
63 unsigned len)
64 {
65 srandom(1);
66 for(unsigned dex=0; dex<len; dex++) {
67 *ptext++ = random();
68 }
69 }
70
71 /* passed to each test */
72 typedef struct {
73 unsigned loops;
74 CSSM_ALGORITHMS algId; // MD5, SHA1
75 bool dumpDigest;
76 } TestParams;
77
78 #define MAX_DIGEST_SIZE 64 // we provide, no malloc below CSSM
79
80 #define PTEXT_SIZE 1000 // to digest in bytes
81 #define INNER_LOOPS 500
82
83
84 /* SHA1 digest is not orthoganal, fix up here */
85 static void ckSha1Final(
86 void *ctx,
87 unsigned char *digest)
88 {
89 sha1GetDigest((sha1Obj)ctx, digest);
90 }
91
92 typedef void (*ckInitFcn)(void *digestCtx);
93 typedef void (*ckUpdateFcn)(void *digestCtx, const void *data, unsigned len);
94 typedef void (*ckFinalFcn)(void *digestCtx, unsigned char *digest);
95
96 static CSSM_RETURN hashDataRateCryptKit(
97 TestParams *params)
98 {
99 ckUpdateFcn updatePtr = NULL;
100 ckFinalFcn finalPtr = NULL;
101 ckInitFcn initPtr = NULL;
102 struct MD5Context md5;
103 sha1Obj sha;
104 void *ctx;
105
106 unsigned loop;
107 unsigned iloop;
108 double startTime, endTime;
109 double timeSpent, timeSpentMs;
110 uint8 ptext[PTEXT_SIZE];
111 uint8 digest[MAX_DIGEST_SIZE];
112 unsigned digestLen = 16;
113
114 /* we reuse this one inside the loop */
115 switch(params->algId) {
116 case CSSM_ALGID_SHA1:
117 sha = sha1Alloc();
118 ctx = sha;
119 initPtr = (ckInitFcn)sha1Reinit;
120 updatePtr = (ckUpdateFcn)sha1AddData;
121 finalPtr = (ckFinalFcn)ckSha1Final;
122 digestLen = 20;
123 break;
124 case CSSM_ALGID_MD5:
125 ctx = &md5;
126 initPtr = (ckInitFcn)MD5Init;
127 updatePtr = (ckUpdateFcn)MD5Update;
128 finalPtr = (ckFinalFcn)MD5Final;
129 break;
130 default:
131 printf("***Sorry, CryptKit can only do SHA1 and MD5.\n");
132 return 1;
133 }
134
135 /* random data, const thru the loops */
136 initPtext(ptext, PTEXT_SIZE);
137
138 /* start critical timing loop */
139 startTime = CFAbsoluteTimeGetCurrent();
140 for(loop=0; loop<params->loops; loop++) {
141 initPtr(ctx);
142 for(iloop=0; iloop<INNER_LOOPS; iloop++) {
143 updatePtr(ctx, ptext, PTEXT_SIZE);
144 }
145 finalPtr(ctx, digest);
146 }
147 endTime = CFAbsoluteTimeGetCurrent();
148 timeSpent = endTime - startTime;
149 timeSpentMs = timeSpent * 1000.0;
150
151 float bytesPerLoop = INNER_LOOPS * PTEXT_SIZE;
152 float totalBytes = params->loops * bytesPerLoop;
153
154 /* careful, KByte = 1024, ms = 1/1000 */
155 printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n",
156 bytesPerLoop, params->loops,
157 timeSpentMs, timeSpentMs / (double)params->loops,
158 ((float)totalBytes / 1024.0) / timeSpent);
159 if(params->dumpDigest) {
160 dumpDigest(digest, digestLen);
161 }
162 return CSSM_OK;
163 }
164
165 typedef union {
166 CC_MD5_CTX md5;
167 CC_SHA1_CTX sha;
168 CC_SHA256_CTX sha256;
169 CC_SHA512_CTX sha512;
170 } CC_CTX;
171
172 typedef void (*ccInitFcn)(void *digestCtx);
173 typedef void (*ccUpdateFcn)(void *digestCtx, const void *data, CC_LONG len);
174 typedef void (*ccFinalFcn)(unsigned char *digest, void *digestCtx);
175
176 static CSSM_RETURN hashDataRateCommonCrypto(
177 TestParams *params)
178 {
179 CC_CTX ctx;
180 ccUpdateFcn updatePtr = NULL;
181 ccFinalFcn finalPtr = NULL;
182 ccInitFcn initPtr = NULL;
183 unsigned loop;
184 unsigned iloop;
185 double startTime, endTime;
186 double timeSpent, timeSpentMs;
187 uint8 ptext[PTEXT_SIZE];
188 uint8 digest[MAX_DIGEST_SIZE];
189 unsigned digestLen = 16;
190
191 /* we reuse this one inside the loop */
192 switch(params->algId) {
193 case CSSM_ALGID_SHA1:
194 initPtr = (ccInitFcn)CC_SHA1_Init;
195 updatePtr = (ccUpdateFcn)CC_SHA1_Update;
196 finalPtr = (ccFinalFcn)CC_SHA1_Final;
197 digestLen = 20;
198 break;
199 case CSSM_ALGID_SHA224:
200 initPtr = (ccInitFcn)CC_SHA224_Init;
201 updatePtr = (ccUpdateFcn)CC_SHA224_Update;
202 finalPtr = (ccFinalFcn)CC_SHA224_Final;
203 digestLen = 28;
204 break;
205 case CSSM_ALGID_SHA256:
206 initPtr = (ccInitFcn)CC_SHA256_Init;
207 updatePtr = (ccUpdateFcn)CC_SHA256_Update;
208 finalPtr = (ccFinalFcn)CC_SHA256_Final;
209 digestLen = 32;
210 break;
211 case CSSM_ALGID_SHA384:
212 initPtr = (ccInitFcn)CC_SHA384_Init;
213 updatePtr = (ccUpdateFcn)CC_SHA384_Update;
214 finalPtr = (ccFinalFcn)CC_SHA384_Final;
215 digestLen = 48;
216 break;
217 case CSSM_ALGID_SHA512:
218 initPtr = (ccInitFcn)CC_SHA512_Init;
219 updatePtr = (ccUpdateFcn)CC_SHA512_Update;
220 finalPtr = (ccFinalFcn)CC_SHA512_Final;
221 digestLen = 64;
222 break;
223 case CSSM_ALGID_MD5:
224 initPtr = (ccInitFcn)CC_MD5_Init;
225 updatePtr = (ccUpdateFcn)CC_MD5_Update;
226 finalPtr = (ccFinalFcn)CC_MD5_Final;
227 digestLen = 16;
228 break;
229 default:
230 printf("***BRRRZAP!\n");
231 return 1;
232 }
233
234 /* random data, const thru the loops */
235 initPtext(ptext, PTEXT_SIZE);
236
237 /* start critical timing loop */
238 startTime = CFAbsoluteTimeGetCurrent();
239 for(loop=0; loop<params->loops; loop++) {
240 initPtr(&ctx);
241 for(iloop=0; iloop<INNER_LOOPS; iloop++) {
242 updatePtr(&ctx, ptext, PTEXT_SIZE);
243 }
244 finalPtr(digest, &ctx);
245 }
246 endTime = CFAbsoluteTimeGetCurrent();
247 timeSpent = endTime - startTime;
248 timeSpentMs = timeSpent * 1000.0;
249
250 float bytesPerLoop = INNER_LOOPS * PTEXT_SIZE;
251 float totalBytes = params->loops * bytesPerLoop;
252
253 /* careful, KByte = 1024, ms = 1/1000 */
254 printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n",
255 bytesPerLoop, params->loops,
256 timeSpentMs, timeSpentMs / (double)params->loops,
257 ((float)totalBytes / 1024.0) / timeSpent);
258 if(params->dumpDigest) {
259 dumpDigest(digest, digestLen);
260 }
261 return CSSM_OK;
262 }
263
264 typedef CSSM_RETURN (*testRunFcn)(TestParams *testParams);
265
266 /*
267 * Static declaration of a test
268 */
269 typedef struct {
270 const char *testName;
271 unsigned loops;
272 testRunFcn run;
273 char testSpec; // for t=xxx cmd line opt
274 } TestDefs;
275
276 static TestDefs testDefsCryptKit =
277 { "Large data digest, CryptKit",
278 1000,
279 hashDataRateCryptKit,
280 'd',
281 };
282
283 static TestDefs testDefsCommonCrypto =
284 { "Large data digest, CommonCrypto",
285 1000,
286 hashDataRateCommonCrypto,
287 'd',
288 };
289
290 static void algToAlgId(
291 HT_Alg alg,
292 CSSM_ALGORITHMS *algId,
293 const char **algStr)
294 {
295 switch(alg) {
296 case HA_MD5:
297 *algId = CSSM_ALGID_MD5;
298 *algStr = "MD5";
299 break;
300 case HA_SHA1:
301 *algId = CSSM_ALGID_SHA1;
302 *algStr = "SHA1";
303 break;
304 case HA_SHA224:
305 *algId = CSSM_ALGID_SHA224;
306 *algStr = "SHA224";
307 break;
308 case HA_SHA256:
309 *algId = CSSM_ALGID_SHA256;
310 *algStr = "SHA256";
311 break;
312 case HA_SHA384:
313 *algId = CSSM_ALGID_SHA384;
314 *algStr = "SHA384";
315 break;
316 case HA_SHA512:
317 *algId = CSSM_ALGID_SHA512;
318 *algStr = "SHA512";
319 break;
320 default:
321 printf("***algToAlgId screwup\n");
322 exit(1);
323 }
324 }
325
326 int main(int argc, char **argv)
327 {
328 TestParams testParams;
329 TestDefs *testDefs = NULL;
330 CSSM_RETURN crtn;
331 int arg;
332 char *argp;
333 unsigned cmdLoops = 0; // can be specified in cmd line
334 // if not, use TestDefs.loops
335 HT_Alg alg;
336 const char *algStr;
337 int firstAlg = FIRST_ALG;
338 int lastAlg = LAST_ALG;
339
340 memset(&testParams, 0, sizeof(testParams));
341
342 if(argc < 2) {
343 usage(argv);
344 }
345 switch(argv[1][0]) {
346 case 'c':
347 testDefs = &testDefsCommonCrypto;
348 break;
349 case 'k':
350 testDefs = &testDefsCryptKit;
351 break;
352 default:
353 usage(argv);
354 }
355
356 for(arg=2; arg<argc; arg++) {
357 argp = argv[arg];
358 switch(argp[0]) {
359 case 'l':
360 cmdLoops = atoi(&argp[2]);
361 break;
362 case 'a':
363 if(argp[1] == '\0') {
364 usage(argv);
365 }
366 switch(argp[2]) {
367 case 'm':
368 firstAlg = lastAlg = HA_MD5;
369 break;
370 case 's':
371 firstAlg = lastAlg = HA_SHA1;
372 break;
373 case '4':
374 firstAlg = lastAlg = HA_SHA224;
375 break;
376 case '2':
377 firstAlg = lastAlg = HA_SHA256;
378 break;
379 case '3':
380 firstAlg = lastAlg = HA_SHA384;
381 break;
382 case '5':
383 firstAlg = lastAlg = HA_SHA512;
384 break;
385 default:
386 usage(argv);
387 }
388 break;
389 case 'v':
390 testParams.dumpDigest = true;
391 break;
392 default:
393 usage(argv);
394 }
395 }
396
397 printf("%s:\n", testDefs->testName);
398 if(cmdLoops) {
399 /* user specified */
400 testParams.loops = cmdLoops;
401 }
402 else {
403 /* default */
404 testParams.loops = testDefs->loops;
405 }
406 if((lastAlg > HA_SHA1) && (testDefs == &testDefsCryptKit)) {
407 /* CryptKit can only do MD5 and SHA1 */
408 lastAlg = HA_SHA1;
409 }
410 for(alg=firstAlg; alg<=lastAlg; alg++) {
411 algToAlgId(alg, &testParams.algId, &algStr);
412 printf(" === %s ===\n", algStr);
413 crtn = testDefs->run(&testParams);
414 if(crtn) {
415 printf("***Error detected in test, somehow....aborting.\n");
416 exit(1);
417 }
418 }
419 return 0;
420 }