]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/badmac/badmac.c
Security-57031.10.10.tar.gz
[apple/security.git] / SecurityTests / cspxutils / badmac / badmac.c
1 /* Copyright (c) 1997,2003-2005,2008 Apple Inc.
2 *
3 * badmac.c - Verify bad MAC detect.
4 *
5 * Revision History
6 * ----------------
7 * 4 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 21 Dec 1998 Doug Mitchell at Apple
10 * Created.
11 */
12 /*
13 * text size = {random, from 100 bytes to 1 megabyte, 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 random MAC key;
21 * generate MAC, validate;
22 * for various bytes of ptext {
23 * corrupt text byte;
24 * verify bad MAC;
25 * restore corrupted byte;
26 * }
27 * }
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <time.h>
33 #include <string.h>
34 #include <Security/cssm.h>
35 #include "cspwrap.h"
36 #include "common.h"
37 #include "cspdlTesting.h"
38
39 #define USAGE_NAME "noUsage"
40 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
41
42 /*
43 * HMAC/SHA1 can not do multiple updates with BSAFE (though the CSP's current
44 * internal implementation can.)
45 * Fixed in Puma; the bug was in BSAFE.
46 */
47 #define HMACSHA_MULTI_UPDATES 1
48
49 /*
50 * Defaults.
51 */
52 #define LOOPS_DEF 10
53 #define MIN_EXP 2 /* for data size 10**exp */
54 #define DEFAULT_MAX_EXP 2
55 #define MAX_EXP 5
56 #define INCR_DEFAULT 0 /* munge every incr bytes - zero means
57 * "adjust per ptext size" */
58
59 /*
60 * Enumerate algs our own way to allow iteration.
61 */
62 #define ALG_SHA1HMAC 1
63 #define ALG_MD5HMAC 2
64 #define ALG_FIRST ALG_SHA1HMAC
65 #define ALG_LAST ALG_MD5HMAC
66 #define MAX_DATA_SIZE (100000 + 100) /* bytes */
67
68 static void usage(char **argv)
69 {
70 printf("usage: %s [options]\n", argv[0]);
71 printf(" Options:\n");
72 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
73 printf(" n=minExp (default=%d)\n", MIN_EXP);
74 printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP);
75 printf(" i=increment (default=%d)\n", INCR_DEFAULT);
76 printf(" r(eference keys only)\n");
77 printf(" m (CSM mallocs MAC)\n");
78 printf(" p=pauseInterval (default=0, no pause)\n");
79 printf(" D (CSP/DL; default = bare CSP)\n");
80 printf(" v(erbose)\n");
81 printf(" q(uiet)\n");
82 printf(" h(elp)\n");
83 exit(1);
84 }
85
86 #define LOG_FREQ 20
87 static int doTest(CSSM_CSP_HANDLE cspHand,
88 uint32 macAlg, // CSSM_ALGID_xxx mac algorithm
89 CSSM_DATA_PTR ptext,
90 CSSM_BOOL verbose,
91 CSSM_BOOL quiet,
92 unsigned keySize,
93 unsigned incr,
94 CSSM_BOOL stagedGen,
95 CSSM_BOOL stagedVerify,
96 CSSM_BOOL mallocMac,
97 CSSM_BOOL refKey)
98 {
99 CSSM_KEY_PTR symmKey;
100 CSSM_DATA mac = {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 uint32 keyGenAlg;
109 unsigned loop = 0;
110
111 switch(macAlg) {
112 case CSSM_ALGID_SHA1HMAC:
113 keyGenAlg = CSSM_ALGID_SHA1HMAC;
114 break;
115 case CSSM_ALGID_MD5HMAC:
116 keyGenAlg = CSSM_ALGID_MD5HMAC;
117 break;
118 default:
119 printf("bogus algorithm\n");
120 return 1;
121 }
122 symmKey = cspGenSymKey(cspHand,
123 keyGenAlg,
124 "noLabel",
125 7,
126 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY,
127 keySize,
128 refKey);
129 if(symmKey == NULL) {
130 rtn = testError(quiet);
131 goto abort;
132 }
133 if(stagedGen) {
134 crtn = cspStagedGenMac(cspHand,
135 macAlg,
136 symmKey,
137 ptext,
138 mallocMac,
139 CSSM_TRUE, // multi
140 &mac);
141 }
142 else {
143 crtn = cspGenMac(cspHand,
144 macAlg,
145 symmKey,
146 ptext,
147 &mac);
148 }
149 if(crtn) {
150 rtn = 1;
151 goto abort;
152 }
153 if(stagedVerify) {
154 crtn = cspStagedMacVerify(cspHand,
155 macAlg,
156 symmKey,
157 ptext,
158 &mac,
159 CSSM_TRUE, // multi
160 CSSM_OK); // expectedResult
161 }
162 else {
163 crtn = cspMacVerify(cspHand,
164 macAlg,
165 symmKey,
166 ptext,
167 &mac,
168 CSSM_OK);
169 }
170 if(crtn) {
171 printf("**Unexpected BAD MAC\n");
172 return testError(quiet);
173 }
174 data = (unsigned char *)ptext->Data;
175 length = ptext->Length;
176 for(byte=0; byte<length; byte += incr) {
177 if(verbose && ((loop++ % LOG_FREQ) == 0)) {
178 printf(" ..byte %d\n", byte);
179 }
180 origData = data[byte];
181 /*
182 * Generate random non-zero byte
183 */
184 do {
185 bits = genRand(1, 0xff) & 0xff;
186 } while(bits == 0);
187 data[byte] ^= bits;
188 if(stagedVerify) {
189 crtn = cspStagedMacVerify(cspHand,
190 macAlg,
191 symmKey,
192 ptext,
193 &mac,
194 CSSM_TRUE, // multi
195 CSSMERR_CSP_VERIFY_FAILED); // expect failure
196 }
197 else {
198 crtn = cspMacVerify(cspHand,
199 macAlg,
200 symmKey,
201 ptext,
202 &mac,
203 CSSMERR_CSP_VERIFY_FAILED);
204 }
205 if(crtn) {
206 return testError(quiet);
207 }
208 data[byte] = origData;
209 }
210 abort:
211 /* free key */
212 if(cspFreeKey(cspHand, symmKey)) {
213 printf("Error freeing symmKey\n");
214 rtn = 1;
215 }
216 CSSM_FREE(mac.Data);
217 return rtn;
218 }
219
220 int main(int argc, char **argv)
221 {
222 int arg;
223 char *argp;
224 unsigned loop;
225 CSSM_DATA ptext;
226 CSSM_CSP_HANDLE CSPHandle;
227 CSSM_BOOL stagedSign;
228 CSSM_BOOL stagedVfy;
229 CSSM_BOOL mallocMac;
230 CSSM_BOOL refKey;
231 const char *algStr;
232 unsigned actualIncr;
233 uint32 macAlg; // CSSM_ALGID_xxx
234 unsigned currAlg; // ALG_xxx
235 int i;
236 int rtn = 0;
237
238 /*
239 * User-spec'd params
240 */
241 unsigned loops = LOOPS_DEF;
242 CSSM_BOOL verbose = CSSM_FALSE;
243 unsigned minExp = MIN_EXP;
244 unsigned maxExp = DEFAULT_MAX_EXP;
245 CSSM_BOOL quiet = CSSM_FALSE;
246 unsigned keySizeInBits = CSP_KEY_SIZE_DEFAULT;
247 unsigned incr = INCR_DEFAULT;
248 unsigned minAlg = ALG_FIRST;
249 uint32 maxAlg = ALG_LAST;
250 unsigned pauseInterval = 0;
251 CSSM_BOOL bareCsp = CSSM_TRUE;
252 CSSM_BOOL refKeysOnly = CSSM_FALSE;
253 CSSM_BOOL cspMallocs = CSSM_FALSE;
254
255 #if macintosh
256 argc = ccommand(&argv);
257 #endif
258 for(arg=1; arg<argc; arg++) {
259 argp = argv[arg];
260 switch(argp[0]) {
261 /* no Alg or keySizeInBits spec for now */
262 case 'l':
263 loops = atoi(&argp[2]);
264 break;
265 case 'n':
266 minExp = atoi(&argp[2]);
267 break;
268 case 'x':
269 maxExp = atoi(&argp[2]);
270 if(maxExp > MAX_EXP) {
271 usage(argv);
272 }
273 break;
274 case 'i':
275 incr = atoi(&argp[2]);
276 break;
277 case 'p':
278 pauseInterval = atoi(&argp[2]);
279 break;
280 case 'D':
281 bareCsp = CSSM_FALSE;
282 #if CSPDL_ALL_KEYS_ARE_REF
283 refKeysOnly = CSSM_TRUE;
284 #endif
285 break;
286 case 'r':
287 refKeysOnly = CSSM_TRUE;
288 break;
289 case 'm':
290 cspMallocs = CSSM_TRUE;
291 break;
292 case 'v':
293 verbose = CSSM_TRUE;
294 break;
295 case 'q':
296 quiet = CSSM_TRUE;
297 break;
298 case 'h':
299 default:
300 usage(argv);
301 }
302 }
303 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE);
304 /* length set in test loop */
305 if(ptext.Data == NULL) {
306 printf("Insufficient heap\n");
307 exit(1);
308 }
309 printf("Starting badmac; args: ");
310 for(i=1; i<argc; i++) {
311 printf("%s ", argv[i]);
312 }
313 printf("\n");
314 CSPHandle = cspDlDbStartup(bareCsp, NULL);
315 if(CSPHandle == 0) {
316 exit(1);
317 }
318 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
319 switch(currAlg) {
320 case ALG_SHA1HMAC:
321 macAlg = CSSM_ALGID_SHA1HMAC;
322 algStr = "SHA1HMAC";
323 break;
324 case ALG_MD5HMAC:
325 macAlg = CSSM_ALGID_MD5HMAC;
326 algStr = "MD5HMAC";
327 break;
328 }
329 if(!quiet) {
330 printf("Testing alg %s\n", algStr);
331 }
332 for(loop=1; ; loop++) {
333 ptext.Length = genData(ptext.Data, minExp, maxExp, DT_Random);
334 if(!quiet) {
335 printf("..loop %d text size %lu\n", loop, ptext.Length);
336 }
337 if(incr == 0) {
338 /* adjust increment as appropriate */
339 actualIncr = (ptext.Length / 50) + 1;
340 }
341 else {
342 actualIncr = incr;
343 }
344 /* mix up staging & ref key format*/
345 stagedSign = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
346 stagedVfy = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
347 if(refKeysOnly) {
348 refKey = CSSM_TRUE;
349 }
350 else {
351 refKey = (loop & 4) ? CSSM_TRUE : CSSM_FALSE;
352 }
353 if(cspMallocs) {
354 mallocMac = CSSM_FALSE;
355 }
356 else {
357 mallocMac = (loop & 8) ? CSSM_TRUE : CSSM_FALSE;
358 }
359
360 #if !HMACSHA_MULTI_UPDATES
361 if(macAlg == CSSM_ALGID_SHA1HMAC) {
362 stagedSign = stagedVfy = CSSM_FALSE;
363 }
364 #endif /* HMACSHA_MULTI_UPDATES */
365
366 if(!quiet) {
367 printf(" stagedSign %d stagedVfy %d refKey %d mallocMac %d\n",
368 (int)stagedSign, (int)stagedVfy, (int)refKey, (int)mallocMac);
369 }
370 if(doTest(CSPHandle,
371 macAlg,
372 &ptext,
373 verbose,
374 quiet,
375 keySizeInBits,
376 actualIncr,
377 stagedSign,
378 stagedVfy,
379 mallocMac,
380 refKey)) {
381 rtn = 1;
382 goto testDone;
383 }
384 if(loops && (loop == loops)) {
385 break;
386 }
387 if(pauseInterval && ((loop % pauseInterval) == 0)) {
388 fpurge(stdin);
389 printf("Hit CR to proceed: ");
390 getchar();
391 }
392 } /* for loop */
393 } /* for alg */
394 testDone:
395 CSSM_ModuleDetach(CSPHandle);
396 if((rtn == 0) && !quiet) {
397 printf("%s test complete\n", argv[0]);
398 }
399 return rtn;
400 }