Example #1
0
/* 
 * Test harness for CCCryptor with lots of options. 
 */
CCCryptorStatus doCCCrypt(
	bool forEncrypt,
	CCAlgorithm encrAlg,			
	bool doCbc,
	bool doPadding,
	const void *keyBytes, size_t keyLen,
	const void *iv,
	bool randUpdates,
	bool inPlace,								/* !doPadding only */
	size_t ctxSize,								/* if nonzero, we allocate ctx */
	bool askOutSize,
	const uint8_t *inText, size_t inTextLen,
	uint8_t **outText, size_t *outTextLen)		/* both returned, WE malloc */
{
	CCCryptorRef	cryptor = NULL;
	CCCryptorStatus crtn;
	CCOperation		op = forEncrypt ? kCCEncrypt : kCCDecrypt;
	CCOptions		options = 0;
	uint8_t			*outBuf = NULL;			/* mallocd output buffer */
	uint8_t			*outp;					/* running ptr into outBuf */
	const uint8		*inp;					/* running ptr into inText */
	size_t			outLen;					/* bytes remaining in outBuf */
	size_t			toMove;					/* bytes remaining in inText */
	size_t			thisMoveOut;			/* output from CCCryptUpdate()/CCCryptFinal() */
	size_t			outBytes;				/* total bytes actually produced in outBuf */
	char			ctx[CC_MAX_CTX_SIZE];	/* for CCCryptorCreateFromData() */
	uint8_t			*textMarker = NULL;		/* 8 bytes of marker here after expected end of 
											 * output */
	char			*ctxMarker = NULL;		/* ditto for caller-provided context */
	unsigned		dex;
	size_t			askedOutSize;			/* from the lib */
	size_t			thisOutLen;				/* dataOutAvailable we use */
	
	if(ctxSize > CC_MAX_CTX_SIZE) {
		printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n");
		exit(1);
	}
	if(!doCbc) {
		options |= kCCOptionECBMode;
	}
	if(doPadding) {
		options |= kCCOptionPKCS7Padding;
	}
	
	/* just hack this one */
	outLen = inTextLen;
	if(forEncrypt) {
		outLen += MAX_BLOCK_SIZE;
	}
	
	outBuf = (uint8_t *)malloc(outLen + MARKER_LENGTH);
	memset(outBuf, 0xEE, outLen + MARKER_LENGTH);
	
	/* library should not touch this memory */
	textMarker = outBuf + outLen;
	memset(textMarker, MARKER_BYTE, MARKER_LENGTH);
	
	/* subsequent errors to errOut: */

	if(inPlace) {
		memmove(outBuf, inText, inTextLen);
		inp = outBuf;
	}
	else {
		inp = inText;
	}

	if(!randUpdates) {
		/* one shot */
		if(askOutSize) {
			crtn = CCCrypt(op, encrAlg, options,
				keyBytes, keyLen, iv,
				inp, inTextLen,
				outBuf, 0, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printf("   alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n",
					(int)encrAlg, (unsigned long)inTextLen, (int)doCbc, (int)doPadding,
					(unsigned long)keyLen);
				printCCError("CCCrypt", crtn);
				crtn = -1;
				goto errOut;
			}
			outLen = askedOutSize;
		}
		crtn = CCCrypt(op, encrAlg, options,
			keyBytes, keyLen, iv,
			inp, inTextLen,
			outBuf, outLen, &outLen);
		if(crtn) {
			printCCError("CCCrypt", crtn);
			goto errOut;
		}
		*outText = outBuf;
		*outTextLen = outLen;
		goto errOut;
	}
	
	/* random multi updates */
	if(ctxSize) {
		size_t ctxSizeCreated;
		
		if(askOutSize) {
			crtn = CCCryptorCreateFromData(op, encrAlg, options,
				keyBytes, keyLen, iv,
				ctx, 0 /* ctxSize */,
				&cryptor, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printCCError("CCCryptorCreateFromData", crtn);
				crtn = -1;
				goto errOut;
			}
			ctxSize = askedOutSize;
		}
		crtn = CCCryptorCreateFromData(op, encrAlg, options,
			keyBytes, keyLen, iv,
			ctx, ctxSize, &cryptor, &ctxSizeCreated);
		if(crtn) {
			printCCError("CCCryptorCreateFromData", crtn);
			return crtn;
		}
		ctxMarker = ctx + ctxSizeCreated;
		memset(ctxMarker, MARKER_BYTE, MARKER_LENGTH);
	}
	else {
		crtn = CCCryptorCreate(op, encrAlg, options,
			keyBytes, keyLen, iv,
			&cryptor);
		if(crtn) {
			printCCError("CCCryptorCreate", crtn);
			return crtn;
		}
	}
	
	toMove = inTextLen;		/* total to go */
	outp = outBuf;
	outBytes = 0;			/* bytes actually produced in outBuf */
	
	while(toMove) {
		uint32 thisMoveIn;			/* input to CCryptUpdate() */
		
		thisMoveIn = genRand(1, toMove);
		logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); 
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, thisMoveIn, false);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn,
			outp, thisOutLen, &thisMoveOut);
		if(crtn) {
			printCCError("CCCryptorUpdate", crtn);
			goto errOut;
		}
		inp			+= thisMoveIn;
		toMove		-= thisMoveIn;
		outp		+= thisMoveOut;
		outLen   	-= thisMoveOut;
		outBytes	+= thisMoveOut;
	}
	
	if(doPadding) {
		/* Final is not needed if padding is disabled */
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, 0, true);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorFinal(cryptor, outp, thisOutLen, &thisMoveOut);
	}
	else {
		thisMoveOut = 0;
		crtn = kCCSuccess;
	}
	
	if(crtn) {
		printCCError("CCCryptorFinal", crtn);
		goto errOut;
	}
	
	outBytes += thisMoveOut;
	*outText = outBuf;
	*outTextLen = outBytes;
	crtn = kCCSuccess;

	for(dex=0; dex<MARKER_LENGTH; dex++) {
		if(textMarker[dex] != MARKER_BYTE) {
			printf("***lib scribbled on our textMarker memory (op=%s)!\n",
				forEncrypt ? "encrypt" : "decrypt");
			crtn = (CCCryptorStatus)-1;
		}
	}
	if(ctxSize) {
		for(dex=0; dex<MARKER_LENGTH; dex++) {
			if(ctxMarker[dex] != MARKER_BYTE) {
				printf("***lib scribbled on our ctxMarker memory (op=%s)!\n",
					forEncrypt ? "encrypt" : "decrypt");
				crtn = (CCCryptorStatus)-1;
			}
		}
	}
	
errOut:
	if(crtn) {
		if(outBuf) {
			free(outBuf);
		}
	}
	if(cryptor) {
		CCCryptorRelease(cryptor);
	}
	return crtn;
}
int main(int argc, char **argv)
{
	unsigned loops = LOOPS_DEF;
	unsigned bufSize = BUFSIZE_DEF;
	unsigned algFirst = ALG_FIRST;
	unsigned algLast = ALG_LAST;
	bool ecbMode = false;
	extern char *optarg;
	int arg;
	while ((arg = getopt(argc, argv, "a:l:b:eh")) != -1) {
		switch (arg) {
			case 'a':
				switch(optarg[0]) {
					case 'a':
						algFirst = algLast = ALG_AES_128;
						break;
					case 'n':
						algFirst = algLast = ALG_AES_192;
						break;
					case 'A':
						algFirst = algLast = ALG_AES_256;
						break;
					case 'd':
						algFirst = algLast = ALG_DES;
						break;
					case '3':
						algFirst = algLast = ALG_3DES;
						break;
					case 'c':
						algFirst = algLast = ALG_CAST;
					case '4':
						algFirst = algLast = ALG_RC4;
				}
				break;
			case 'l':
				loops = atoi(optarg);
				break;
			case 'b':
				bufSize = atoi(optarg);
				break;
			case 'e':
				ecbMode = true;
				break;
			case 'h':
				usage(argv);
		}
	}
	if(optind != argc) {
		usage(argv);
	}

	/* 
	 * encrypt and decrypt on workBuf
	 * save original ptext in saveBuf, compare at end as sanity check 
	 *   for ECB only
	 */
	unsigned char *workBuf = (unsigned char *)malloc(bufSize);
	unsigned char *saveBuf = (unsigned char *)malloc(bufSize);
	if((workBuf == NULL) || (saveBuf == NULL)) {
		printf("***malloc failure\n");
		exit(1);
	}
	appGetRandomBytes(workBuf, bufSize);
	memmove(saveBuf, workBuf, bufSize);
	
	uint8_t keyBytes[MAX_KEY_SIZE];
	size_t keyLength;
	
	appGetRandomBytes(keyBytes, MAX_KEY_SIZE);
	
	CCCryptorRef cryptor;
	CCAlgorithm alg;
	CCOptions options = 0;
	OSStatus ortn;
	
	if(ecbMode) {
		options |= kCCOptionECBMode;
	}
	
	unsigned currAlg;
	for(currAlg=algFirst; currAlg<=algLast; currAlg++) {
		const char *algStr = NULL;
		
		switch(currAlg) {
			case ALG_DES:
				keyLength = kCCKeySizeDES;
				alg = kCCAlgorithmDES;
				algStr = "DES ";
				break;
			case ALG_3DES:
				keyLength = kCCKeySize3DES;
				alg = kCCAlgorithm3DES;
				algStr = "3DES";
				break;
			case ALG_AES_128:
				keyLength = kCCKeySizeAES128;
				alg = kCCAlgorithmAES128;
				algStr = "AES128";
				break;
			case ALG_AES_192:
				keyLength = kCCKeySizeAES192;
				alg = kCCAlgorithmAES128;
				algStr = "AES192";
				break;
			case ALG_AES_256:
				keyLength = kCCKeySizeAES256;
				alg = kCCAlgorithmAES128;
				algStr = "AES256";
				break;
			case ALG_CAST:
				keyLength = kCCKeySizeMaxCAST;
				alg = kCCAlgorithmCAST;
				algStr = "CAST";
				break;
			case ALG_RC4:
				keyLength = kCCKeySizeMaxRC4;
				alg = kCCAlgorithmRC4;
				algStr = "RC4";
				break;
		}
		
		printf("Algorithm: %s  keySize: %u  mode: %s  loops: %u  bufSize: %u\n",
			algStr, (unsigned)keyLength, ecbMode ? "ECB" : "CBC",
			(unsigned)loops, (unsigned)bufSize);
			
		CFAbsoluteTime start, end;
		unsigned loop;
		size_t thisMoved;
		
		/* encrypt: GO */
		start = CFAbsoluteTimeGetCurrent();
		
		ortn = CCCryptorCreate(kCCEncrypt, alg, options,
			keyBytes, keyLength, NULL, &cryptor);
		if(ortn) {
			printCCError("CCCryptorCreate", ortn);
			exit(1);
		}
		
		for(loop=0; loop<loops; loop++) {
			ortn = CCCryptorUpdate(cryptor, workBuf, bufSize,
				workBuf, bufSize, &thisMoved);
			if(ortn) {
				printCCError("CCCryptorUpdate", ortn);
				exit(1);
			}
		}
		/* no padding, CCCryptFinal not needed */
		end = CFAbsoluteTimeGetCurrent();
		
		printf("   encrypt %u * %u bytes took %gs: %g KBytes/s\n",
			(unsigned)loops, (unsigned)bufSize,
			end - start,
			(loops * bufSize) / (end - start) / 1024.0);
			
		/* dncrypt: GO */
		start = CFAbsoluteTimeGetCurrent();
		
		ortn = CCCryptorCreate(kCCDecrypt, alg, options,
			keyBytes, keyLength, NULL, &cryptor);
		if(ortn) {
			printCCError("CCCryptorCreate", ortn);
			exit(1);
		}
		
		for(loop=0; loop<loops; loop++) {
			ortn = CCCryptorUpdate(cryptor, workBuf, bufSize,
				workBuf, bufSize, &thisMoved);
			if(ortn) {
				printCCError("CCCryptorUpdate", ortn);
				exit(1);
			}
		}
		/* no padding, CCCryptFinal not needed */
		end = CFAbsoluteTimeGetCurrent();
		
		printf("   decrypt %u * %u bytes took %gs: %g KBytes/s\n",
			(unsigned)loops, (unsigned)bufSize,
			end - start,
			(loops * bufSize) / (end - start) / 1024.0);
			
		if(ecbMode) {
			if(memcmp(workBuf, saveBuf, bufSize)) {
				printf("***plaintext miscompare!\n");
			}
		}
	}
	return 0;
}