]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ccHmacClone/ccHmacClone.cpp
Security-57740.31.2.tar.gz
[apple/security.git] / SecurityTests / cspxutils / ccHmacClone / ccHmacClone.cpp
1 /*
2 * ccHmacClone - test CommonCrypto's clone context for HMAC.
3 *
4 * Written 3/30/2006 by Doug Mitchell.
5 */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <time.h>
10 #include "common.h"
11 #include <string.h>
12 #include <CommonCrypto/CommonHMAC.h>
13
14 /*
15 * Defaults.
16 */
17 #define LOOPS_DEF 200
18
19 #define MIN_DATA_SIZE 8
20 #define MAX_DATA_SIZE 10000 /* bytes */
21 #define MIN_KEY_SIZE 1
22 #define MAX_KEY_SIZE 256 /* bytes */
23 #define LOOP_NOTIFY 20
24
25 /*
26 * Enumerate algs our own way to allow iteration.
27 */
28 typedef enum {
29 ALG_MD5 = 1,
30 ALG_SHA1,
31 ALG_SHA224,
32 ALG_SHA256,
33 ALG_SHA384,
34 ALG_SHA512,
35 } HmacAlg;
36 #define ALG_FIRST ALG_MD5
37 #define ALG_LAST ALG_SHA512
38
39 #define LOG_SIZE 0
40 #if LOG_SIZE
41 #define logSize(s) printf s
42 #else
43 #define logSize(s)
44 #endif
45
46 static void usage(char **argv)
47 {
48 printf("usage: %s [options]\n", argv[0]);
49 printf(" Options:\n");
50 printf(" a=algorithm (5=MD5; s=SHA1; 4=SHA224; 2=SHA256; 3=SHA384; 1=SHA512; default=all)\n");
51 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
52 printf(" k=keySizeInBytes\n");
53 printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE);
54 printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE);
55 printf(" p=pauseInterval (default=0, no pause)\n");
56 printf(" s (all ops single-shot, not staged)\n");
57 printf(" S (all ops staged)\n");
58 printf(" z (keys and plaintext all zeroes)\n");
59 printf(" v(erbose)\n");
60 printf(" q(uiet)\n");
61 printf(" h(elp)\n");
62 exit(1);
63 }
64
65 /*
66 * Given an initialized CCHmacContext, feed it some data and get the result.
67 */
68 static void hmacRun(
69 CCHmacContext *ctx,
70 bool randomUpdates,
71 const unsigned char *ptext,
72 size_t ptextLen,
73 void *dataOut)
74 {
75 while(ptextLen) {
76 size_t thisMoveIn; /* input to CCryptUpdate() */
77
78 if(randomUpdates) {
79 thisMoveIn = genRand(1, ptextLen);
80 }
81 else {
82 thisMoveIn = ptextLen;
83 }
84 logSize(("###ptext segment (1) len %lu\n", (unsigned long)thisMoveIn));
85 CCHmacUpdate(ctx, ptext, thisMoveIn);
86 ptext += thisMoveIn;
87 ptextLen -= thisMoveIn;
88 }
89 CCHmacFinal(ctx, dataOut);
90 }
91
92
93 #define MAX_HMAC_SIZE CC_SHA512_DIGEST_LENGTH
94
95 static int doTest(const uint8_t *ptext,
96 size_t ptextLen,
97 CCHmacAlgorithm hmacAlg,
98 uint32 keySizeInBytes,
99 bool stagedOrig,
100 bool stagedClone,
101 bool quiet,
102 bool verbose)
103 {
104 uint8_t keyBytes[MAX_KEY_SIZE];
105 uint8_t hmacOrig[MAX_HMAC_SIZE];
106 uint8_t hmacClone[MAX_HMAC_SIZE];
107 int rtn = 0;
108 CCHmacContext ctxOrig;
109 CCHmacContext ctxClone;
110 unsigned die; /* 0..3 indicates when to clone */
111 unsigned loopNum = 0;
112 size_t hmacLen;
113 bool didClone = false;
114
115 switch(hmacAlg) {
116 case kCCHmacAlgSHA1:
117 hmacLen = CC_SHA1_DIGEST_LENGTH;
118 break;
119 case kCCHmacAlgMD5:
120 hmacLen = CC_MD5_DIGEST_LENGTH;
121 break;
122 case kCCHmacAlgSHA224:
123 hmacLen = CC_SHA224_DIGEST_LENGTH;
124 break;
125 case kCCHmacAlgSHA256:
126 hmacLen = CC_SHA256_DIGEST_LENGTH;
127 break;
128 case kCCHmacAlgSHA384:
129 hmacLen = CC_SHA384_DIGEST_LENGTH;
130 break;
131 case kCCHmacAlgSHA512:
132 hmacLen = CC_SHA512_DIGEST_LENGTH;
133 break;
134 default:
135 printf("***BRRRZAP!\n");
136 exit(1);
137 }
138
139 /* random key */
140 appGetRandomBytes(keyBytes, keySizeInBytes);
141
142 /* cook up first context */
143 CCHmacInit(&ctxOrig, hmacAlg, keyBytes, keySizeInBytes);
144
145 /* roll the dice */
146 die = genRand(0, 3);
147
148 /*
149 * In this loop we do updates to the ctxOrig up until we
150 * clone it, then we use hmacRun to finish both of them.
151 */
152 while(ptextLen) {
153 if((die == loopNum) || !stagedOrig) {
154 /* make the clone now */
155 if(verbose) {
156 printf(" ...cloning at loop %u\n", loopNum);
157 }
158 ctxClone = ctxOrig;
159 didClone = true;
160
161 /* do all of the clone's updates and final here */
162 hmacRun(&ctxClone, stagedClone, ptext, ptextLen, hmacClone);
163
164 /* now do all remaining updates and final for original */
165 hmacRun(&ctxOrig, stagedOrig, ptext, ptextLen, hmacOrig);
166
167 /* we're all done, time to check the HMAC values */
168 break;
169 } /* making clone */
170
171 /* feed some data into cryptorOrig */
172 size_t thisMove;
173 if(stagedOrig) {
174 thisMove = genRand(1, ptextLen);
175 }
176 else {
177 thisMove = ptextLen;
178 }
179 logSize(("###ptext segment (2) len %lu\n", (unsigned long)thisMove));
180 CCHmacUpdate(&ctxOrig, ptext, thisMove);
181 ptext += thisMove;
182 ptextLen -= thisMove;
183 loopNum++;
184 }
185
186 /*
187 * It's possible to get here without cloning or doing any finals,
188 * if we ran thru multiple updates and finished ptextLen for cryptorOrig
189 * before we hit the cloning spot.
190 */
191 if(!didClone) {
192 if(!quiet) {
193 printf("...ctxOrig finished before we cloned; skipping test\n");
194 }
195 return 0;
196 }
197 if(memcmp(hmacOrig, hmacClone, hmacLen)) {
198 printf("***data miscompare\n");
199 rtn = testError(quiet);
200 }
201 return rtn;
202 }
203
204 bool isBitSet(unsigned bit, unsigned word)
205 {
206 if(bit > 31) {
207 printf("We don't have that many bits\n");
208 exit(1);
209 }
210 unsigned mask = 1 << bit;
211 return (word & mask) ? true : false;
212 }
213
214 int main(int argc, char **argv)
215 {
216 int arg;
217 char *argp;
218 unsigned loop;
219 uint8 *ptext;
220 size_t ptextLen;
221 bool stagedOrig;
222 bool stagedClone;
223 const char *algStr;
224 CCHmacAlgorithm hmacAlg;
225 int i;
226 int currAlg; // ALG_xxx
227 uint32 keySizeInBytes;
228 int rtn = 0;
229
230 /*
231 * User-spec'd params
232 */
233 bool keySizeSpec = false; // false: use rand key size
234 HmacAlg minAlg = ALG_FIRST;
235 HmacAlg maxAlg = ALG_LAST;
236 unsigned loops = LOOPS_DEF;
237 bool verbose = false;
238 size_t minPtextSize = MIN_DATA_SIZE;
239 size_t maxPtextSize = MAX_DATA_SIZE;
240 bool quiet = false;
241 unsigned pauseInterval = 0;
242 bool stagedSpec = false; // true means caller fixed stagedOrig and stagedClone
243
244 for(arg=1; arg<argc; arg++) {
245 argp = argv[arg];
246 switch(argp[0]) {
247 case 'a':
248 if(argp[1] != '=') {
249 usage(argv);
250 }
251 switch(argp[2]) {
252 case '5':
253 minAlg = maxAlg = ALG_MD5;
254 break;
255 case 's':
256 minAlg = maxAlg = ALG_SHA1;
257 break;
258 case '4':
259 minAlg = maxAlg = ALG_SHA224;
260 break;
261 case '2':
262 minAlg = maxAlg = ALG_SHA256;
263 break;
264 case '3':
265 minAlg = maxAlg = ALG_SHA384;
266 break;
267 case '1':
268 minAlg = maxAlg = ALG_SHA512;
269 break;
270 default:
271 usage(argv);
272 }
273 break;
274 case 'l':
275 loops = atoi(&argp[2]);
276 break;
277 case 'n':
278 minPtextSize = atoi(&argp[2]);
279 break;
280 case 'm':
281 maxPtextSize = atoi(&argp[2]);
282 break;
283 case 'k':
284 keySizeInBytes = atoi(&argp[2]);
285 keySizeSpec = true;
286 break;
287 case 'v':
288 verbose = true;
289 break;
290 case 'q':
291 quiet = true;
292 break;
293 case 'p':
294 pauseInterval = atoi(&argp[2]);;
295 break;
296 case 's':
297 stagedOrig = stagedClone = false;
298 stagedSpec = true;
299 break;
300 case 'S':
301 stagedOrig = stagedClone = true;
302 stagedSpec = true;
303 break;
304 case 'h':
305 default:
306 usage(argv);
307 }
308 }
309 ptext = (uint8 *)malloc(maxPtextSize);
310 if(ptext == NULL) {
311 printf("Insufficient heap space\n");
312 exit(1);
313 }
314 /* ptext length set in test loop */
315
316 printf("Starting ccHmacClone; args: ");
317 for(i=1; i<argc; i++) {
318 printf("%s ", argv[i]);
319 }
320 printf("\n");
321
322 if(pauseInterval) {
323 fpurge(stdin);
324 printf("Top of test; hit CR to proceed: ");
325 getchar();
326 }
327
328 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
329 /* when zero, set size randomly or per user setting */
330 switch(currAlg) {
331 case ALG_MD5:
332 hmacAlg = kCCHmacAlgMD5;
333 algStr = "HMACMD5";
334 break;
335 case ALG_SHA1:
336 hmacAlg = kCCHmacAlgSHA1;
337 algStr = "HMACSHA1";
338 break;
339 case ALG_SHA224:
340 hmacAlg = kCCHmacAlgSHA224;
341 algStr = "HMACSHA224";
342 break;
343 case ALG_SHA256:
344 hmacAlg = kCCHmacAlgSHA256;
345 algStr = "HMACSHA256";
346 break;
347 case ALG_SHA384:
348 hmacAlg = kCCHmacAlgSHA384;
349 algStr = "HMACSHA384";
350 break;
351 case ALG_SHA512:
352 hmacAlg = kCCHmacAlgSHA512;
353 algStr = "HMACSHA512";
354 break;
355 default:
356 printf("***BRRZAP!\n");
357 exit(1);
358 }
359 if(!quiet || verbose) {
360 printf("Testing alg %s\n", algStr);
361 }
362 for(loop=1; ; loop++) {
363 ptextLen = genRand(minPtextSize, maxPtextSize);
364 appGetRandomBytes(ptext, ptextLen);
365 if(!keySizeSpec) {
366 keySizeInBytes = genRand(MIN_KEY_SIZE, MAX_KEY_SIZE);
367 }
368
369 /* per-loop settings */
370 if(!stagedSpec) {
371 stagedOrig = isBitSet(1, loop);
372 stagedClone = isBitSet(2, loop);
373 }
374
375 if(!quiet) {
376 if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
377 printf("..loop %d ptextLen %4lu keySize %3lu stagedOrig=%d "
378 "stagedClone=%d\n",
379 loop, (unsigned long)ptextLen, (unsigned long)keySizeInBytes,
380 (int)stagedOrig, (int)stagedClone);
381 }
382 }
383
384 if(doTest(ptext, ptextLen,
385 hmacAlg, keySizeInBytes,
386 stagedOrig, stagedClone, quiet, verbose)) {
387 rtn = 1;
388 break;
389 }
390 if(pauseInterval && ((loop % pauseInterval) == 0)) {
391 char c;
392 fpurge(stdin);
393 printf("Hit CR to proceed, q to abort: ");
394 c = getchar();
395 if(c == 'q') {
396 goto testDone;
397 }
398 }
399 if(loops && (loop == loops)) {
400 break;
401 }
402 } /* main loop */
403 if(rtn) {
404 break;
405 }
406
407 } /* for algs */
408
409 testDone:
410 if(pauseInterval) {
411 fpurge(stdin);
412 printf("ModuleDetach/Unload complete; hit CR to exit: ");
413 getchar();
414 }
415 if((rtn == 0) && !quiet) {
416 printf("%s test complete\n", argv[0]);
417 }
418 free(ptext);
419 return rtn;
420 }
421
422