/* Copyright (c) 1997,2003-2005,2008 Apple Inc. * * badmac.c - Verify bad MAC detect. * * Revision History * ---------------- * 4 May 2000 Doug Mitchell * Ported to X/CDSA2. * 21 Dec 1998 Doug Mitchell at Apple * Created. */ /* * text size = {random, from 100 bytes to 1 megabyte, in * geometrical steps, i.e. the number of * bytes would be 10^r, where r is random out of * {2,3,4,5,6}, plus a random integer in {0,..99}}; * * for loop_count * text contents = {random data, random size as specified above}; * generate random MAC key; * generate MAC, validate; * for various bytes of ptext { * corrupt text byte; * verify bad MAC; * restore corrupted byte; * } * } */ #include #include #include #include #include #include "cspwrap.h" #include "common.h" #include "cspdlTesting.h" #define USAGE_NAME "noUsage" #define USAGE_NAME_LEN (strlen(USAGE_NAME)) /* * HMAC/SHA1 can not do multiple updates with BSAFE (though the CSP's current * internal implementation can.) * Fixed in Puma; the bug was in BSAFE. */ #define HMACSHA_MULTI_UPDATES 1 /* * Defaults. */ #define LOOPS_DEF 10 #define MIN_EXP 2 /* for data size 10**exp */ #define DEFAULT_MAX_EXP 2 #define MAX_EXP 5 #define INCR_DEFAULT 0 /* munge every incr bytes - zero means * "adjust per ptext size" */ /* * Enumerate algs our own way to allow iteration. */ #define ALG_SHA1HMAC 1 #define ALG_MD5HMAC 2 #define ALG_FIRST ALG_SHA1HMAC #define ALG_LAST ALG_MD5HMAC #define MAX_DATA_SIZE (100000 + 100) /* bytes */ static void usage(char **argv) { printf("usage: %s [options]\n", argv[0]); printf(" Options:\n"); printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); printf(" n=minExp (default=%d)\n", MIN_EXP); printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); printf(" i=increment (default=%d)\n", INCR_DEFAULT); printf(" r(eference keys only)\n"); printf(" m (CSM mallocs MAC)\n"); printf(" p=pauseInterval (default=0, no pause)\n"); printf(" D (CSP/DL; default = bare CSP)\n"); printf(" v(erbose)\n"); printf(" q(uiet)\n"); printf(" h(elp)\n"); exit(1); } #define LOG_FREQ 20 static int doTest(CSSM_CSP_HANDLE cspHand, uint32 macAlg, // CSSM_ALGID_xxx mac algorithm CSSM_DATA_PTR ptext, CSSM_BOOL verbose, CSSM_BOOL quiet, unsigned keySize, unsigned incr, CSSM_BOOL stagedGen, CSSM_BOOL stagedVerify, CSSM_BOOL mallocMac, CSSM_BOOL refKey) { CSSM_KEY_PTR symmKey; CSSM_DATA mac = {0, NULL}; unsigned length; unsigned byte; unsigned char *data; unsigned char origData; unsigned char bits; int rtn = 0; CSSM_RETURN crtn; uint32 keyGenAlg; unsigned loop = 0; switch(macAlg) { case CSSM_ALGID_SHA1HMAC: keyGenAlg = CSSM_ALGID_SHA1HMAC; break; case CSSM_ALGID_MD5HMAC: keyGenAlg = CSSM_ALGID_MD5HMAC; break; default: printf("bogus algorithm\n"); return 1; } symmKey = cspGenSymKey(cspHand, keyGenAlg, "noLabel", 7, CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY, keySize, refKey); if(symmKey == NULL) { rtn = testError(quiet); goto abort; } if(stagedGen) { crtn = cspStagedGenMac(cspHand, macAlg, symmKey, ptext, mallocMac, CSSM_TRUE, // multi &mac); } else { crtn = cspGenMac(cspHand, macAlg, symmKey, ptext, &mac); } if(crtn) { rtn = 1; goto abort; } if(stagedVerify) { crtn = cspStagedMacVerify(cspHand, macAlg, symmKey, ptext, &mac, CSSM_TRUE, // multi CSSM_OK); // expectedResult } else { crtn = cspMacVerify(cspHand, macAlg, symmKey, ptext, &mac, CSSM_OK); } if(crtn) { printf("**Unexpected BAD MAC\n"); return testError(quiet); } data = (unsigned char *)ptext->Data; length = ptext->Length; for(byte=0; byte MAX_EXP) { usage(argv); } break; case 'i': incr = atoi(&argp[2]); break; case 'p': pauseInterval = atoi(&argp[2]); break; case 'D': bareCsp = CSSM_FALSE; #if CSPDL_ALL_KEYS_ARE_REF refKeysOnly = CSSM_TRUE; #endif break; case 'r': refKeysOnly = CSSM_TRUE; break; case 'm': cspMallocs = CSSM_TRUE; break; case 'v': verbose = CSSM_TRUE; break; case 'q': quiet = CSSM_TRUE; break; case 'h': default: usage(argv); } } ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); /* length set in test loop */ if(ptext.Data == NULL) { printf("Insufficient heap\n"); exit(1); } printf("Starting badmac; args: "); for(i=1; i