1 /* Copyright (c) 1997,2003-2005,2008 Apple Inc.
3 * badmac.c - Verify bad MAC detect.
7 * 4 May 2000 Doug Mitchell
9 * 21 Dec 1998 Doug Mitchell at Apple
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}};
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 {
25 * restore corrupted byte;
34 #include <Security/cssm.h>
37 #include "cspdlTesting.h"
39 #define USAGE_NAME "noUsage"
40 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
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.
47 #define HMACSHA_MULTI_UPDATES 1
53 #define MIN_EXP 2 /* for data size 10**exp */
54 #define DEFAULT_MAX_EXP 2
56 #define INCR_DEFAULT 0 /* munge every incr bytes - zero means
57 * "adjust per ptext size" */
60 * Enumerate algs our own way to allow iteration.
62 #define ALG_SHA1HMAC 1
64 #define ALG_FIRST ALG_SHA1HMAC
65 #define ALG_LAST ALG_MD5HMAC
66 #define MAX_DATA_SIZE (100000 + 100) /* bytes */
68 static void usage(char **argv
)
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");
87 static int doTest(CSSM_CSP_HANDLE cspHand
,
88 uint32 macAlg
, // CSSM_ALGID_xxx mac algorithm
95 CSSM_BOOL stagedVerify
,
100 CSSM_DATA mac
= {0, NULL
};
104 unsigned char origData
;
112 case CSSM_ALGID_SHA1HMAC
:
113 keyGenAlg
= CSSM_ALGID_SHA1HMAC
;
115 case CSSM_ALGID_MD5HMAC
:
116 keyGenAlg
= CSSM_ALGID_MD5HMAC
;
119 printf("bogus algorithm\n");
122 symmKey
= cspGenSymKey(cspHand
,
126 CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY
,
129 if(symmKey
== NULL
) {
130 rtn
= testError(quiet
);
134 crtn
= cspStagedGenMac(cspHand
,
143 crtn
= cspGenMac(cspHand
,
154 crtn
= cspStagedMacVerify(cspHand
,
160 CSSM_OK
); // expectedResult
163 crtn
= cspMacVerify(cspHand
,
171 printf("**Unexpected BAD MAC\n");
172 return testError(quiet
);
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
);
180 origData
= data
[byte
];
182 * Generate random non-zero byte
185 bits
= genRand(1, 0xff) & 0xff;
189 crtn
= cspStagedMacVerify(cspHand
,
195 CSSMERR_CSP_VERIFY_FAILED
); // expect failure
198 crtn
= cspMacVerify(cspHand
,
203 CSSMERR_CSP_VERIFY_FAILED
);
206 return testError(quiet
);
208 data
[byte
] = origData
;
212 if(cspFreeKey(cspHand
, symmKey
)) {
213 printf("Error freeing symmKey\n");
220 int main(int argc
, char **argv
)
226 CSSM_CSP_HANDLE CSPHandle
;
227 CSSM_BOOL stagedSign
;
233 uint32 macAlg
; // CSSM_ALGID_xxx
234 unsigned currAlg
; // ALG_xxx
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
;
256 argc
= ccommand(&argv
);
258 for(arg
=1; arg
<argc
; arg
++) {
261 /* no Alg or keySizeInBits spec for now */
263 loops
= atoi(&argp
[2]);
266 minExp
= atoi(&argp
[2]);
269 maxExp
= atoi(&argp
[2]);
270 if(maxExp
> MAX_EXP
) {
275 incr
= atoi(&argp
[2]);
278 pauseInterval
= atoi(&argp
[2]);
281 bareCsp
= CSSM_FALSE
;
282 #if CSPDL_ALL_KEYS_ARE_REF
283 refKeysOnly
= CSSM_TRUE
;
287 refKeysOnly
= CSSM_TRUE
;
290 cspMallocs
= CSSM_TRUE
;
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");
309 printf("Starting badmac; args: ");
310 for(i
=1; i
<argc
; i
++) {
311 printf("%s ", argv
[i
]);
314 CSPHandle
= cspDlDbStartup(bareCsp
, NULL
);
318 for(currAlg
=minAlg
; currAlg
<=maxAlg
; currAlg
++) {
321 macAlg
= CSSM_ALGID_SHA1HMAC
;
325 macAlg
= CSSM_ALGID_MD5HMAC
;
330 printf("Testing alg %s\n", algStr
);
332 for(loop
=1; ; loop
++) {
333 ptext
.Length
= genData(ptext
.Data
, minExp
, maxExp
, DT_Random
);
335 printf("..loop %d text size %lu\n", loop
, ptext
.Length
);
338 /* adjust increment as appropriate */
339 actualIncr
= (ptext
.Length
/ 50) + 1;
344 /* mix up staging & ref key format*/
345 stagedSign
= (loop
& 1) ? CSSM_TRUE
: CSSM_FALSE
;
346 stagedVfy
= (loop
& 2) ? CSSM_TRUE
: CSSM_FALSE
;
351 refKey
= (loop
& 4) ? CSSM_TRUE
: CSSM_FALSE
;
354 mallocMac
= CSSM_FALSE
;
357 mallocMac
= (loop
& 8) ? CSSM_TRUE
: CSSM_FALSE
;
360 #if !HMACSHA_MULTI_UPDATES
361 if(macAlg
== CSSM_ALGID_SHA1HMAC
) {
362 stagedSign
= stagedVfy
= CSSM_FALSE
;
364 #endif /* HMACSHA_MULTI_UPDATES */
367 printf(" stagedSign %d stagedVfy %d refKey %d mallocMac %d\n",
368 (int)stagedSign
, (int)stagedVfy
, (int)refKey
, (int)mallocMac
);
384 if(loops
&& (loop
== loops
)) {
387 if(pauseInterval
&& ((loop
% pauseInterval
) == 0)) {
389 printf("Hit CR to proceed: ");
395 CSSM_ModuleDetach(CSPHandle
);
396 if((rtn
== 0) && !quiet
) {
397 printf("%s test complete\n", argv
[0]);