1/* 2 * ccPerform.cpp - measure performance of CommonCrypto encryption 3 */ 4 5#include <stdlib.h> 6#include <strings.h> 7#include <stdio.h> 8#include <unistd.h> 9#include <CoreFoundation/CoreFoundation.h> 10#include <CommonCrypto/CommonCryptor.h> 11#include "common.h" 12#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 13 14#define LOOPS_DEF 1000 15#define BUFSIZE_DEF 10240 16#define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */ 17 18 19/* 20 * Enumerate algs our own way to allow iteration. 21 */ 22typedef enum { 23 ALG_AES_128, 24 ALG_AES_192, 25 ALG_AES_256, 26 ALG_DES, 27 ALG_3DES, 28 ALG_CAST, 29 ALG_RC4 30} SymAlg; 31#define ALG_FIRST ALG_AES_128 32#define ALG_LAST ALG_RC4 33 34static void usage(char **argv) 35{ 36 printf("usage: %s [options]\n", argv[0]); 37 printf("Options:\n"); 38 printf(" -a alg -- alg : d=DES; 3=3DES; a=AES128; n=AES192; A=AES256;\n"); 39 printf(" c=CAST; 4=RC4; default=all\n"); 40 printf(" -l loops -- loops; default %u\n", LOOPS_DEF); 41 printf(" -b bufsize -- buffer size; default %u\n", BUFSIZE_DEF); 42 printf(" -e -- ECB mode; default is CBC\n"); 43 44 exit(1); 45} 46 47static void printCCError(const char *str, OSStatus ortn) 48{ 49 printf("***%s returned %ld\n", str, (long)ortn); 50} 51 52int main(int argc, char **argv) 53{ 54 unsigned loops = LOOPS_DEF; 55 unsigned bufSize = BUFSIZE_DEF; 56 unsigned algFirst = ALG_FIRST; 57 unsigned algLast = ALG_LAST; 58 bool ecbMode = false; 59 extern char *optarg; 60 int arg; 61 while ((arg = getopt(argc, argv, "a:l:b:eh")) != -1) { 62 switch (arg) { 63 case 'a': 64 switch(optarg[0]) { 65 case 'a': 66 algFirst = algLast = ALG_AES_128; 67 break; 68 case 'n': 69 algFirst = algLast = ALG_AES_192; 70 break; 71 case 'A': 72 algFirst = algLast = ALG_AES_256; 73 break; 74 case 'd': 75 algFirst = algLast = ALG_DES; 76 break; 77 case '3': 78 algFirst = algLast = ALG_3DES; 79 break; 80 case 'c': 81 algFirst = algLast = ALG_CAST; 82 case '4': 83 algFirst = algLast = ALG_RC4; 84 } 85 break; 86 case 'l': 87 loops = atoi(optarg); 88 break; 89 case 'b': 90 bufSize = atoi(optarg); 91 break; 92 case 'e': 93 ecbMode = true; 94 break; 95 case 'h': 96 usage(argv); 97 } 98 } 99 if(optind != argc) { 100 usage(argv); 101 } 102 103 /* 104 * encrypt and decrypt on workBuf 105 * save original ptext in saveBuf, compare at end as sanity check 106 * for ECB only 107 */ 108 unsigned char *workBuf = (unsigned char *)malloc(bufSize); 109 unsigned char *saveBuf = (unsigned char *)malloc(bufSize); 110 if((workBuf == NULL) || (saveBuf == NULL)) { 111 printf("***malloc failure\n"); 112 exit(1); 113 } 114 appGetRandomBytes(workBuf, bufSize); 115 memmove(saveBuf, workBuf, bufSize); 116 117 uint8_t keyBytes[MAX_KEY_SIZE]; 118 size_t keyLength; 119 120 appGetRandomBytes(keyBytes, MAX_KEY_SIZE); 121 122 CCCryptorRef cryptor; 123 CCAlgorithm alg; 124 CCOptions options = 0; 125 OSStatus ortn; 126 127 if(ecbMode) { 128 options |= kCCOptionECBMode; 129 } 130 131 unsigned currAlg; 132 for(currAlg=algFirst; currAlg<=algLast; currAlg++) { 133 const char *algStr = NULL; 134 135 switch(currAlg) { 136 case ALG_DES: 137 keyLength = kCCKeySizeDES; 138 alg = kCCAlgorithmDES; 139 algStr = "DES "; 140 break; 141 case ALG_3DES: 142 keyLength = kCCKeySize3DES; 143 alg = kCCAlgorithm3DES; 144 algStr = "3DES"; 145 break; 146 case ALG_AES_128: 147 keyLength = kCCKeySizeAES128; 148 alg = kCCAlgorithmAES128; 149 algStr = "AES128"; 150 break; 151 case ALG_AES_192: 152 keyLength = kCCKeySizeAES192; 153 alg = kCCAlgorithmAES128; 154 algStr = "AES192"; 155 break; 156 case ALG_AES_256: 157 keyLength = kCCKeySizeAES256; 158 alg = kCCAlgorithmAES128; 159 algStr = "AES256"; 160 break; 161 case ALG_CAST: 162 keyLength = kCCKeySizeMaxCAST; 163 alg = kCCAlgorithmCAST; 164 algStr = "CAST"; 165 break; 166 case ALG_RC4: 167 keyLength = kCCKeySizeMaxRC4; 168 alg = kCCAlgorithmRC4; 169 algStr = "RC4"; 170 break; 171 } 172 173 printf("Algorithm: %s keySize: %u mode: %s loops: %u bufSize: %u\n", 174 algStr, (unsigned)keyLength, ecbMode ? "ECB" : "CBC", 175 (unsigned)loops, (unsigned)bufSize); 176 177 CFAbsoluteTime start, end; 178 unsigned loop; 179 size_t thisMoved; 180 181 /* encrypt: GO */ 182 start = CFAbsoluteTimeGetCurrent(); 183 184 ortn = CCCryptorCreate(kCCEncrypt, alg, options, 185 keyBytes, keyLength, NULL, &cryptor); 186 if(ortn) { 187 printCCError("CCCryptorCreate", ortn); 188 exit(1); 189 } 190 191 for(loop=0; loop<loops; loop++) { 192 ortn = CCCryptorUpdate(cryptor, workBuf, bufSize, 193 workBuf, bufSize, &thisMoved); 194 if(ortn) { 195 printCCError("CCCryptorUpdate", ortn); 196 exit(1); 197 } 198 } 199 /* no padding, CCCryptFinal not needed */ 200 end = CFAbsoluteTimeGetCurrent(); 201 202 printf(" encrypt %u * %u bytes took %gs: %g KBytes/s\n", 203 (unsigned)loops, (unsigned)bufSize, 204 end - start, 205 (loops * bufSize) / (end - start) / 1024.0); 206 207 /* dncrypt: GO */ 208 start = CFAbsoluteTimeGetCurrent(); 209 210 ortn = CCCryptorCreate(kCCDecrypt, alg, options, 211 keyBytes, keyLength, NULL, &cryptor); 212 if(ortn) { 213 printCCError("CCCryptorCreate", ortn); 214 exit(1); 215 } 216 217 for(loop=0; loop<loops; loop++) { 218 ortn = CCCryptorUpdate(cryptor, workBuf, bufSize, 219 workBuf, bufSize, &thisMoved); 220 if(ortn) { 221 printCCError("CCCryptorUpdate", ortn); 222 exit(1); 223 } 224 } 225 /* no padding, CCCryptFinal not needed */ 226 end = CFAbsoluteTimeGetCurrent(); 227 228 printf(" decrypt %u * %u bytes took %gs: %g KBytes/s\n", 229 (unsigned)loops, (unsigned)bufSize, 230 end - start, 231 (loops * bufSize) / (end - start) / 1024.0); 232 233 if(ecbMode) { 234 if(memcmp(workBuf, saveBuf, bufSize)) { 235 printf("***plaintext miscompare!\n"); 236 } 237 } 238 } 239 return 0; 240} 241