]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/hashTest/hashTest.c
Security-57740.31.2.tar.gz
[apple/security.git] / SecurityTests / cspxutils / hashTest / hashTest.c
1 /* Copyright (c) 1998,2003-2006,2008 Apple Inc.
2 *
3 * hashTest.c - test CDSA digest functions.
4 *
5 * Revision History
6 * ----------------
7 * 4 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 12 May 1998 Doug Mitchell at Apple
10 * Created.
11 */
12 /*
13 * text size = {random, from 100 bytes to 100k, in
14 * geometrical steps, i.e. the number of
15 * bytes would be 10^r, where r is random out of
16 * {2,3,4,5,6}, plus a random integer in {0,..99}};
17 *
18 * for loop_count
19 * text contents = {random data, random size as specified above};
20 * generate digest in one shot;
21 * generate digest with multiple random-sized updates;
22 * verify digests compare;
23 * for various bytes of text {
24 * corrupt text byte;
25 * generate digest in one shot;
26 * veridy digest is different;
27 * restore corrupted byte;
28 * }
29 * }
30 */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <time.h>
35 #include <string.h>
36 #include <Security/cssm.h>
37 #include "cspwrap.h"
38 #include <Security/cssm.h>
39 #include <Security/cssmapple.h>
40 #include "cspwrap.h"
41 #include "common.h"
42
43 /*
44 * Defaults.
45 */
46 #define LOOPS_DEF 50
47 #define MIN_EXP 2 /* for data size 10**exp */
48 #define DEFAULT_MAX_EXP 3
49 #define MAX_EXP 5
50 #define INCR_DEFAULT 0 /* munge every incr bytes - zero means
51 * "adjust per ptext size" */
52 typedef enum {
53 ALG_MD2 = 1,
54 ALG_MD5,
55 ALG_SHA1,
56 ALG_SHA224,
57 ALG_SHA256,
58 ALG_SHA384,
59 ALG_SHA512
60 };
61
62 #define ALG_FIRST ALG_MD2
63 #define ALG_LAST ALG_SHA512
64 #define MAX_DATA_SIZE (100000 + 100) /* bytes */
65 #define LOOP_NOTIFY 20
66
67 static void usage(char **argv)
68 {
69 printf("usage: %s [options]\n", argv[0]);
70 printf(" Options:\n");
71 printf(" a=algorithm (s=SHA1; m=MD5; M=MD2; 4=SHA224; 2=SHA256; 3=SHA384; 5=SHA512; "
72 "default=all\n");
73 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
74 printf(" n=minExp (default=%d)\n", MIN_EXP);
75 printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP);
76 printf(" i=increment (default=%d)\n", INCR_DEFAULT);
77 printf(" p=pauseInterval (default=0, no pause)\n");
78 printf(" z (zero data)\n");
79 printf(" I (incrementing data)\n");
80 printf(" g (good digest only)\n");
81 printf(" D (CSP/DL; default = bare CSP)\n");
82 printf(" v(erbose)\n");
83 printf(" q(uiet)\n");
84 printf(" h(elp)\n");
85 exit(1);
86 }
87
88 #define LOG_FREQ 20
89
90 static int doTest(CSSM_CSP_HANDLE cspHand,
91 uint32 alg,
92 CSSM_DATA_PTR ptext,
93 CSSM_BOOL verbose,
94 CSSM_BOOL quiet,
95 CSSM_BOOL mallocDigest,
96 unsigned incr,
97 CSSM_BOOL goodOnly)
98 {
99 CSSM_DATA refDigest = {0, NULL};
100 CSSM_DATA testDigest = {0, NULL};
101 unsigned length;
102 unsigned byte;
103 unsigned char *data;
104 unsigned char origData;
105 unsigned char bits;
106 int rtn = 0;
107 CSSM_RETURN crtn;
108 unsigned loop = 0;
109
110 /*
111 * generate digest in one shot;
112 * generate digest with multiple random-sized updates;
113 * verify digests compare;
114 * for various bytes of ptext {
115 * corrupt ptext byte;
116 * generate digest in one shot;
117 * verify digest is different;
118 * restore corrupted byte;
119 * }
120 */
121 crtn = cspDigest(cspHand,
122 alg,
123 mallocDigest,
124 ptext,
125 &refDigest);
126 if(crtn) {
127 rtn = testError(quiet);
128 goto abort;
129 }
130 crtn = cspStagedDigest(cspHand,
131 alg,
132 mallocDigest,
133 CSSM_TRUE, // multi updates
134 ptext,
135 &testDigest);
136 if(crtn) {
137 rtn = testError(quiet);
138 goto abort;
139 }
140 if(refDigest.Length != testDigest.Length) {
141 printf("Digest length mismatch (1)\n");
142 rtn = testError(quiet);
143 goto abort;
144 }
145 if(memcmp(refDigest.Data, testDigest.Data, refDigest.Length)) {
146 printf("Digest miscompare (1)\n");
147 rtn = testError(quiet);
148 if(rtn) {
149 goto abort;
150 }
151 }
152 if(goodOnly) {
153 rtn = 0;
154 goto abort;
155 }
156 appFreeCssmData(&testDigest, CSSM_FALSE);
157 testDigest.Length = 0;
158 data = (unsigned char *)ptext->Data;
159 length = ptext->Length;
160 for(byte=0; byte<length; byte += incr) {
161 if(verbose && ((loop++ % LOG_FREQ) == 0)) {
162 printf("....byte %d\n", byte);
163 }
164 origData = data[byte];
165 /*
166 * Generate random non-zero byte
167 */
168 do {
169 bits = genRand(1, 0xff) & 0xff;
170 } while(bits == 0);
171 data[byte] ^= bits;
172 crtn = cspDigest(cspHand,
173 alg,
174 mallocDigest,
175 ptext,
176 &testDigest);
177 if(crtn) {
178 rtn = testError(quiet);
179 break;
180 }
181 if(!memcmp(refDigest.Data, testDigest.Data, refDigest.Length)) {
182 printf("Unexpected digest compare\n");
183 rtn = testError(quiet);
184 break;
185 }
186 appFreeCssmData(&testDigest, CSSM_FALSE);
187 testDigest.Length = 0;
188 data[byte] = origData;
189 }
190 abort:
191 /* free digests */
192 if(refDigest.Length) {
193 appFreeCssmData(&refDigest, CSSM_FALSE);
194 }
195 if(testDigest.Length) {
196 appFreeCssmData(&testDigest, CSSM_FALSE);
197 }
198 return rtn;
199 }
200
201 int main(int argc, char **argv)
202 {
203 int arg;
204 char *argp;
205 unsigned loop;
206 CSSM_DATA ptext;
207 CSSM_CSP_HANDLE cspHand;
208 CSSM_BOOL mallocDigest;
209 const char *algStr;
210 uint32 alg; // ALG_MD5, etc.
211 uint32 cssmAlg; // CSSM_ALGID_MD5, etc.
212 unsigned actualIncr;
213 int i;
214
215 /*
216 * User-spec'd params
217 */
218 unsigned loops = LOOPS_DEF;
219 CSSM_BOOL verbose = CSSM_FALSE;
220 unsigned minExp = MIN_EXP;
221 unsigned maxExp = DEFAULT_MAX_EXP;
222 CSSM_BOOL quiet = CSSM_FALSE;
223 unsigned incr = INCR_DEFAULT;
224 unsigned minAlg = ALG_FIRST;
225 unsigned maxAlg = ALG_LAST;
226 unsigned pauseInterval = 0;
227 dataType dt;
228 CSSM_BOOL goodOnly = CSSM_FALSE;
229 CSSM_BOOL bareCsp = CSSM_TRUE;
230
231 for(arg=1; arg<argc; arg++) {
232 argp = argv[arg];
233 switch(argp[0]) {
234 case 'a':
235 if(argp[1] != '=') {
236 usage(argv);
237 }
238 switch(argp[2]) {
239 case 's':
240 minAlg = maxAlg = ALG_SHA1;
241 break;
242 case 'm':
243 minAlg = maxAlg = ALG_MD5;
244 break;
245 case 'M':
246 minAlg = maxAlg = ALG_MD2;
247 break;
248 case '4':
249 minAlg = maxAlg = ALG_SHA224;
250 break;
251 case '2':
252 minAlg = maxAlg = ALG_SHA256;
253 break;
254 case '3':
255 minAlg = maxAlg = ALG_SHA384;
256 break;
257 case '5':
258 minAlg = maxAlg = ALG_SHA512;
259 break;
260 default:
261 usage(argv);
262 }
263 break;
264 case 'l':
265 loops = atoi(&argp[2]);
266 break;
267 case 'n':
268 minExp = atoi(&argp[2]);
269 break;
270 case 'x':
271 maxExp = atoi(&argp[2]);
272 if(maxExp > MAX_EXP) {
273 usage(argv);
274 }
275 break;
276 case 'i':
277 incr = atoi(&argp[2]);
278 break;
279 case 'p':
280 pauseInterval = atoi(&argp[2]);;
281 break;
282 case 'v':
283 verbose = CSSM_TRUE;
284 break;
285 case 'q':
286 quiet = CSSM_TRUE;
287 break;
288 case 'D':
289 bareCsp = CSSM_FALSE;
290 break;
291 case 'z':
292 dt = DT_Zero;
293 break;
294 case 'I':
295 dt = DT_Increment;
296 break;
297 case 'g':
298 goodOnly = CSSM_TRUE;
299 break;
300 case 'h':
301 default:
302 usage(argv);
303 }
304 }
305 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE);
306 /* length set in test loop */
307 if(ptext.Data == NULL) {
308 printf("Insufficient heap\n");
309 exit(1);
310 }
311
312 printf("Starting hashTest; args: ");
313 for(i=1; i<argc; i++) {
314 printf("%s ", argv[i]);
315 }
316 printf("\n");
317 cspHand = cspDlDbStartup(bareCsp, NULL);
318 if(cspHand == 0) {
319 exit(1);
320 }
321
322 for(alg=minAlg; alg<=maxAlg; alg++) {
323 switch(alg) {
324 case ALG_MD5:
325 algStr = "MD5";
326 cssmAlg = CSSM_ALGID_MD5;
327 break;
328 case ALG_MD2:
329 algStr = "MD2";
330 cssmAlg = CSSM_ALGID_MD2;
331 break;
332 case ALG_SHA1:
333 algStr = "SHA1";
334 cssmAlg = CSSM_ALGID_SHA1;
335 break;
336 case ALG_SHA224:
337 algStr = "SHA224";
338 cssmAlg = CSSM_ALGID_SHA224;
339 break;
340 case ALG_SHA256:
341 algStr = "SHA256";
342 cssmAlg = CSSM_ALGID_SHA256;
343 break;
344 case ALG_SHA384:
345 algStr = "SHA384";
346 cssmAlg = CSSM_ALGID_SHA384;
347 break;
348 case ALG_SHA512:
349 algStr = "SHA512";
350 cssmAlg = CSSM_ALGID_SHA512;
351 break;
352 }
353 if(!quiet) {
354 printf("Testing alg %s\n", algStr);
355 }
356 for(loop=1; ; loop++) {
357 ptext.Length = genData(ptext.Data, minExp, maxExp, dt);
358 if(incr == 0) {
359 /* adjust increment as appropriate */
360 actualIncr = (ptext.Length / 50) + 1;
361 }
362 else {
363 actualIncr = incr;
364 }
365 /* mix up mallocing */
366 mallocDigest = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
367 if(!quiet) {
368 if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
369 printf("..loop %d text size %lu mallocDigest %d\n",
370 loop, (unsigned long)ptext.Length, (int)mallocDigest);
371 }
372 }
373 if(doTest(cspHand,
374 cssmAlg,
375 &ptext,
376 verbose,
377 quiet,
378 mallocDigest,
379 actualIncr,
380 goodOnly)) {
381 exit(1);
382 }
383 if(loops && (loop == loops)) {
384 break;
385 }
386 if(pauseInterval && ((loop % pauseInterval) == 0)) {
387 fpurge(stdin);
388 printf("Hit CR to proceed: ");
389 getchar();
390 }
391 }
392 }
393 if(!quiet) {
394 printf("%s test complete\n", argv[0]);
395 }
396 return 0;
397 }