#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
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);
}
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;
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);
}
}
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);
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);
}
}
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;
}