2 * hashTimeSA.cpp - measure performance of digest ops, standalone version (no
3 * dependency on Security.framewortk or on CommonCrypto portion of libSystem).
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>
16 /* enumerate digest algorithms our way */
27 #define FIRST_ALG HA_MD5
28 #define LAST_ALG HA_SHA512
30 static void usage(char **argv
)
32 printf("Usage: %s c|k [option ...]\n", argv
[0]);
33 printf(" c=CommonCrypto; k=CryptKit\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");
47 static void dumpDigest(
48 const unsigned char *digest
,
51 for(unsigned dex
=0; dex
<len
; dex
++) {
52 printf("%02X", *digest
++);
60 /* sort-of random, but repeatable */
61 static void initPtext(
66 for(unsigned dex
=0; dex
<len
; dex
++) {
71 /* passed to each test */
74 CSSM_ALGORITHMS algId
; // MD5, SHA1
78 #define MAX_DIGEST_SIZE 64 // we provide, no malloc below CSSM
80 #define PTEXT_SIZE 1000 // to digest in bytes
81 #define INNER_LOOPS 500
84 /* SHA1 digest is not orthoganal, fix up here */
85 static void ckSha1Final(
87 unsigned char *digest
)
89 sha1GetDigest((sha1Obj
)ctx
, digest
);
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
);
96 static CSSM_RETURN
hashDataRateCryptKit(
99 ckUpdateFcn updatePtr
= NULL
;
100 ckFinalFcn finalPtr
= NULL
;
101 ckInitFcn initPtr
= NULL
;
102 struct MD5Context md5
;
108 double startTime
, endTime
;
109 double timeSpent
, timeSpentMs
;
110 uint8 ptext
[PTEXT_SIZE
];
111 uint8 digest
[MAX_DIGEST_SIZE
];
112 unsigned digestLen
= 16;
114 /* we reuse this one inside the loop */
115 switch(params
->algId
) {
116 case CSSM_ALGID_SHA1
:
119 initPtr
= (ckInitFcn
)sha1Reinit
;
120 updatePtr
= (ckUpdateFcn
)sha1AddData
;
121 finalPtr
= (ckFinalFcn
)ckSha1Final
;
126 initPtr
= (ckInitFcn
)MD5Init
;
127 updatePtr
= (ckUpdateFcn
)MD5Update
;
128 finalPtr
= (ckFinalFcn
)MD5Final
;
131 printf("***Sorry, CryptKit can only do SHA1 and MD5.\n");
135 /* random data, const thru the loops */
136 initPtext(ptext
, PTEXT_SIZE
);
138 /* start critical timing loop */
139 startTime
= CFAbsoluteTimeGetCurrent();
140 for(loop
=0; loop
<params
->loops
; loop
++) {
142 for(iloop
=0; iloop
<INNER_LOOPS
; iloop
++) {
143 updatePtr(ctx
, ptext
, PTEXT_SIZE
);
145 finalPtr(ctx
, digest
);
147 endTime
= CFAbsoluteTimeGetCurrent();
148 timeSpent
= endTime
- startTime
;
149 timeSpentMs
= timeSpent
* 1000.0;
151 float bytesPerLoop
= INNER_LOOPS
* PTEXT_SIZE
;
152 float totalBytes
= params
->loops
* bytesPerLoop
;
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
);
168 CC_SHA256_CTX sha256
;
169 CC_SHA512_CTX sha512
;
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
);
176 static CSSM_RETURN
hashDataRateCommonCrypto(
180 ccUpdateFcn updatePtr
= NULL
;
181 ccFinalFcn finalPtr
= NULL
;
182 ccInitFcn initPtr
= NULL
;
185 double startTime
, endTime
;
186 double timeSpent
, timeSpentMs
;
187 uint8 ptext
[PTEXT_SIZE
];
188 uint8 digest
[MAX_DIGEST_SIZE
];
189 unsigned digestLen
= 16;
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
;
199 case CSSM_ALGID_SHA224
:
200 initPtr
= (ccInitFcn
)CC_SHA224_Init
;
201 updatePtr
= (ccUpdateFcn
)CC_SHA224_Update
;
202 finalPtr
= (ccFinalFcn
)CC_SHA224_Final
;
205 case CSSM_ALGID_SHA256
:
206 initPtr
= (ccInitFcn
)CC_SHA256_Init
;
207 updatePtr
= (ccUpdateFcn
)CC_SHA256_Update
;
208 finalPtr
= (ccFinalFcn
)CC_SHA256_Final
;
211 case CSSM_ALGID_SHA384
:
212 initPtr
= (ccInitFcn
)CC_SHA384_Init
;
213 updatePtr
= (ccUpdateFcn
)CC_SHA384_Update
;
214 finalPtr
= (ccFinalFcn
)CC_SHA384_Final
;
217 case CSSM_ALGID_SHA512
:
218 initPtr
= (ccInitFcn
)CC_SHA512_Init
;
219 updatePtr
= (ccUpdateFcn
)CC_SHA512_Update
;
220 finalPtr
= (ccFinalFcn
)CC_SHA512_Final
;
224 initPtr
= (ccInitFcn
)CC_MD5_Init
;
225 updatePtr
= (ccUpdateFcn
)CC_MD5_Update
;
226 finalPtr
= (ccFinalFcn
)CC_MD5_Final
;
230 printf("***BRRRZAP!\n");
234 /* random data, const thru the loops */
235 initPtext(ptext
, PTEXT_SIZE
);
237 /* start critical timing loop */
238 startTime
= CFAbsoluteTimeGetCurrent();
239 for(loop
=0; loop
<params
->loops
; loop
++) {
241 for(iloop
=0; iloop
<INNER_LOOPS
; iloop
++) {
242 updatePtr(&ctx
, ptext
, PTEXT_SIZE
);
244 finalPtr(digest
, &ctx
);
246 endTime
= CFAbsoluteTimeGetCurrent();
247 timeSpent
= endTime
- startTime
;
248 timeSpentMs
= timeSpent
* 1000.0;
250 float bytesPerLoop
= INNER_LOOPS
* PTEXT_SIZE
;
251 float totalBytes
= params
->loops
* bytesPerLoop
;
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
);
264 typedef CSSM_RETURN (*testRunFcn
)(TestParams
*testParams
);
267 * Static declaration of a test
270 const char *testName
;
273 char testSpec
; // for t=xxx cmd line opt
276 static TestDefs testDefsCryptKit
=
277 { "Large data digest, CryptKit",
279 hashDataRateCryptKit
,
283 static TestDefs testDefsCommonCrypto
=
284 { "Large data digest, CommonCrypto",
286 hashDataRateCommonCrypto
,
290 static void algToAlgId(
292 CSSM_ALGORITHMS
*algId
,
297 *algId
= CSSM_ALGID_MD5
;
301 *algId
= CSSM_ALGID_SHA1
;
305 *algId
= CSSM_ALGID_SHA224
;
309 *algId
= CSSM_ALGID_SHA256
;
313 *algId
= CSSM_ALGID_SHA384
;
317 *algId
= CSSM_ALGID_SHA512
;
321 printf("***algToAlgId screwup\n");
326 int main(int argc
, char **argv
)
328 TestParams testParams
;
329 TestDefs
*testDefs
= NULL
;
333 unsigned cmdLoops
= 0; // can be specified in cmd line
334 // if not, use TestDefs.loops
337 int firstAlg
= FIRST_ALG
;
338 int lastAlg
= LAST_ALG
;
340 memset(&testParams
, 0, sizeof(testParams
));
347 testDefs
= &testDefsCommonCrypto
;
350 testDefs
= &testDefsCryptKit
;
356 for(arg
=2; arg
<argc
; arg
++) {
360 cmdLoops
= atoi(&argp
[2]);
363 if(argp
[1] == '\0') {
368 firstAlg
= lastAlg
= HA_MD5
;
371 firstAlg
= lastAlg
= HA_SHA1
;
374 firstAlg
= lastAlg
= HA_SHA224
;
377 firstAlg
= lastAlg
= HA_SHA256
;
380 firstAlg
= lastAlg
= HA_SHA384
;
383 firstAlg
= lastAlg
= HA_SHA512
;
390 testParams
.dumpDigest
= true;
397 printf("%s:\n", testDefs
->testName
);
400 testParams
.loops
= cmdLoops
;
404 testParams
.loops
= testDefs
->loops
;
406 if((lastAlg
> HA_SHA1
) && (testDefs
== &testDefsCryptKit
)) {
407 /* CryptKit can only do MD5 and SHA1 */
410 for(alg
=firstAlg
; alg
<=lastAlg
; alg
++) {
411 algToAlgId(alg
, &testParams
.algId
, &algStr
);
412 printf(" === %s ===\n", algStr
);
413 crtn
= testDefs
->run(&testParams
);
415 printf("***Error detected in test, somehow....aborting.\n");