--- /dev/null
+/*
+ * ccPerform.cpp - measure performance of CommonCrypto encryption
+ */
+
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CommonCrypto/CommonCryptor.h>
+#include "common.h"
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+
+#define LOOPS_DEF 1000
+#define BUFSIZE_DEF 10240
+#define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */
+
+
+/*
+ * Enumerate algs our own way to allow iteration.
+ */
+typedef enum {
+ ALG_AES_128,
+ ALG_AES_192,
+ ALG_AES_256,
+ ALG_DES,
+ ALG_3DES,
+ ALG_CAST,
+ ALG_RC4
+} SymAlg;
+#define ALG_FIRST ALG_AES_128
+#define ALG_LAST ALG_RC4
+
+static void usage(char **argv)
+{
+ printf("usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" -a alg -- alg : d=DES; 3=3DES; a=AES128; n=AES192; A=AES256;\n");
+ printf(" c=CAST; 4=RC4; default=all\n");
+ printf(" -l loops -- loops; default %u\n", LOOPS_DEF);
+ printf(" -b bufsize -- buffer size; default %u\n", BUFSIZE_DEF);
+ printf(" -e -- ECB mode; default is CBC\n");
+
+ exit(1);
+}
+
+static void printCCError(const char *str, OSStatus ortn)
+{
+ printf("***%s returned %ld\n", str, (long)ortn);
+}
+
+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;
+}