]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/perform/perform.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / SecurityTests / cspxutils / perform / perform.cpp
1 /*
2 * CSP symmetric encryption performance measurement tool
3 * Based on Michael Brouwer's cryptoPerformance.cpp
4 *
5 */
6 #include <CoreFoundation/CoreFoundation.h>
7 #include <security_cdsa_utilities/cssmdata.h>
8 #include <security_cdsa_utilities/cssmerrors.h>
9 #include <security_cdsa_client/genkey.h>
10 #include <security_cdsa_client/wrapkey.h>
11 #include <string.h>
12 #include "common.h"
13 #include <iomanip>
14 #include <iostream>
15 #include <memory>
16 using namespace std;
17
18 /*
19 * Default values
20 */
21 #define ALG_DEFAULT CSSM_ALGID_AES
22 #define ALG_STR_DEFAULT "AES"
23 #define CHAIN_DEFAULT CSSM_TRUE
24 #define KEY_SIZE_DEFAULT 128
25
26 #define BEGIN_FUNCTION try {
27
28 #define END_FUNCTION } \
29 catch (const CssmError &e) \
30 { \
31 cssmPerror(__PRETTY_FUNCTION__, e.error); \
32 } \
33 catch (...) \
34 { \
35 fprintf(stderr, "%s: failed\n", __PRETTY_FUNCTION__); \
36 } \
37
38 static void usage(char **argv)
39 {
40 printf("usage: %s iterations bufsize [options]\n", argv[0]);
41 printf(" Options:\n");
42 printf(" a=algorithm (s=ASC; d=DES; 3=3DES; 2=RC2; 4=RC4; 5=RC5;\n");
43 printf(" a=AES; b=Blowfish; c=CAST; n=NULL; default=AES)\n");
44 printf(" k=keySizeInBits\n");
45 printf(" b=blockSizeInBits\n");
46 printf(" e (ECB mode; default is CBC)\n");
47 printf(" i (re-set IV in each loop)\n");
48 printf(" v(erbose)\n");
49 printf(" h(elp)\n");
50 exit(1);
51 }
52
53 static void
54 cdsaSetupContexts(int iterations,
55 auto_ptr<Security::CssmClient::Encrypt> &encrypt,
56 auto_ptr<Security::CssmClient::Decrypt> &decrypt,
57 CSSM_ALGORITHMS keyAlg,
58 CSSM_ALGORITHMS encrAlg,
59 CSSM_ENCRYPT_MODE encrMode,
60 uint32 keySizeInBits,
61 uint32 blockSizeInBits) // optional
62 {
63 BEGIN_FUNCTION
64 Security::CssmClient::CSP csp(gGuidAppleCSP);
65 //CssmData keyData((uint8 *)"1234567812345678", 16);
66 Security::CssmClient::GenerateKey keyGenerator(csp, keyAlg, keySizeInBits);
67 Security::CssmClient::Key key = keyGenerator(Security::CssmClient::KeySpec(
68 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
69 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE));
70 for (int ix=0; ix < iterations; ++ix)
71 {
72 encrypt.reset(new Security::CssmClient::Encrypt(csp, encrAlg));
73 encrypt->mode(encrMode);
74 encrypt->key(key);
75 if(blockSizeInBits) {
76 encrypt->add(CSSM_ATTRIBUTE_BLOCK_SIZE, blockSizeInBits / 8);
77 }
78 //encrypt->activate();
79
80 decrypt.reset(new Security::CssmClient::Decrypt(csp, encrAlg));
81 decrypt->mode(encrMode);
82 decrypt->key(key);
83 if(blockSizeInBits) {
84 decrypt->add(CSSM_ATTRIBUTE_BLOCK_SIZE, blockSizeInBits / 8);
85 }
86 //decrypt->activate();
87 }
88 END_FUNCTION
89 }
90
91 static void
92 cdsaEncrypt(int iterations, Security::CssmClient::Encrypt &encrypt,
93 uint8 *inBuf, uint32 bufLen, uint8 *outBuf, bool useIv, uint32 blockSizeBytes,
94 CSSM_BOOL resetIv)
95 {
96 BEGIN_FUNCTION
97 CssmData iv((uint8 *)"12345678123456781234567812345678", blockSizeBytes);
98 CssmData inData(inBuf, bufLen);
99 CssmData outData(outBuf, bufLen);
100 CssmData nullData(reinterpret_cast<uint8 *>(NULL) + 1, 0);
101 if(useIv) {
102 encrypt.initVector(iv);
103 }
104 if(useIv && resetIv) {
105 for (int ix=0; ix < iterations; ++ix)
106 {
107 encrypt.initVector(iv);
108 encrypt.encrypt(inData, outData, nullData);
109 }
110 }
111 else {
112 for (int ix=0; ix < iterations; ++ix)
113 {
114 encrypt.encrypt(inData, outData, nullData);
115 }
116 }
117 END_FUNCTION
118 }
119
120 static void
121 cdsaDecrypt(int iterations, Security::CssmClient::Decrypt &decrypt,
122 uint8 *inBuf, uint32 bufLen, uint8 *outBuf, bool useIv, uint32 blockSizeBytes,
123 CSSM_BOOL resetIv)
124 {
125 BEGIN_FUNCTION
126 CssmData iv((uint8 *)"12345678123456781234567812345678", blockSizeBytes);
127 CssmData inData(inBuf, bufLen);
128 CssmData outData(outBuf, bufLen);
129 CssmData nullData(reinterpret_cast<uint8 *>(NULL) + 1, 0);
130 if(useIv) {
131 decrypt.initVector(iv);
132 }
133 if(useIv && resetIv) {
134 for (int ix=0; ix < iterations; ++ix)
135 {
136 decrypt.initVector(iv);
137 decrypt.decrypt(inData, outData, nullData);
138 }
139 }
140 else {
141 for (int ix=0; ix < iterations; ++ix)
142 {
143 decrypt.decrypt(inData, outData, nullData);
144 }
145 }
146 END_FUNCTION
147 }
148
149 int main(int argc, char **argv)
150 {
151 int arg;
152 char *argp;
153 CSSM_ENCRYPT_MODE mode;
154 uint32 blockSizeBytes = 8;
155
156 /*
157 * User-spec'd params
158 */
159 CSSM_BOOL chainEnable = CHAIN_DEFAULT;
160 uint32 keySizeInBits = KEY_SIZE_DEFAULT;
161 uint32 blockSizeInBits = 0;
162 const char *algStr = ALG_STR_DEFAULT;
163 uint32 keyAlg = ALG_DEFAULT; // CSSM_ALGID_xxx of the key
164 uint32 encrAlg = ALG_DEFAULT; // CSSM_ALGID_xxx for encrypt
165 int iterations;
166 int bufSize;
167 CSSM_BOOL resetIv = CSSM_FALSE;
168 CSSM_BOOL verbose = false;
169
170 if(argc < 3) {
171 usage(argv);
172 }
173 iterations = atoi(argv[1]);
174 bufSize = atoi(argv[2]);
175 for(arg=3; arg<argc; arg++) {
176 argp = argv[arg];
177 switch(argp[0]) {
178 case 'a':
179 if(argp[1] != '=') {
180 usage(argv);
181 }
182 switch(argp[2]) {
183 case 's':
184 encrAlg = keyAlg = CSSM_ALGID_ASC;
185 algStr = "ASC";
186 break;
187 case 'd':
188 encrAlg = keyAlg = CSSM_ALGID_DES;
189 algStr = "DES";
190 keySizeInBits = 64;
191 break;
192 case '3':
193 keyAlg = CSSM_ALGID_3DES_3KEY;
194 encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
195 algStr = "3DES";
196 keySizeInBits = 64 * 3;
197 break;
198 case '2':
199 encrAlg = keyAlg = CSSM_ALGID_RC2;
200 algStr = "RC2";
201 break;
202 case '4':
203 encrAlg = keyAlg = CSSM_ALGID_RC4;
204 algStr = "RC4";
205 /* not a block cipher */
206 chainEnable = CSSM_FALSE;
207 break;
208 case '5':
209 encrAlg = keyAlg = CSSM_ALGID_RC5;
210 algStr = "RC5";
211 break;
212 case 'a':
213 encrAlg = keyAlg = CSSM_ALGID_AES;
214 algStr = "AES";
215 break;
216 case 'b':
217 encrAlg = keyAlg = CSSM_ALGID_BLOWFISH;
218 algStr = "Blowfish";
219 break;
220 case 'c':
221 encrAlg = keyAlg = CSSM_ALGID_CAST;
222 algStr = "CAST";
223 break;
224 case 'n':
225 encrAlg = keyAlg = CSSM_ALGID_NONE;
226 algStr = "NULL";
227 break;
228 default:
229 usage(argv);
230 }
231 break;
232 case 'k':
233 keySizeInBits = atoi(&argp[2]);
234 break;
235 case 'b':
236 blockSizeInBits = atoi(&argp[2]);
237 break;
238 case 'e':
239 chainEnable = CSSM_FALSE;
240 break;
241 case 'i':
242 resetIv = CSSM_TRUE;
243 break;
244 case 'v':
245 verbose = CSSM_TRUE;
246 break;
247 case 'h':
248 default:
249 usage(argv);
250 }
251 }
252 switch(keyAlg) {
253 case CSSM_ALGID_RC4:
254 chainEnable = CSSM_FALSE;
255 mode = CSSM_ALGMODE_NONE;
256 if((iterations & 1) == 0) {
257 printf("***WARNING: an even number of iterations with RC4 results in\n"
258 " identical plaintext and ciphertext!\n");
259 }
260 break;
261 case CSSM_ALGID_AES:
262 case CSSM_ALGID_NONE:
263 blockSizeBytes = blockSizeInBits ? (blockSizeInBits / 8) : 16;
264 break;
265 default:
266 break;
267 }
268 if(chainEnable) {
269 mode = CSSM_ALGMODE_CBC_IV8;
270 }
271 else {
272 mode = CSSM_ALGMODE_ECB;
273 }
274
275 if(blockSizeInBits) {
276 printf("Algorithm: %s keySize: %u blockSize: %u mode: %s"
277 " iterations: %d bufSize %d\n",
278 algStr, (unsigned)keySizeInBits, (unsigned)blockSizeInBits,
279 chainEnable ? "CBC" : "ECB",
280 iterations, bufSize);
281 }
282 else {
283 printf("Algorithm: %s keySize: %u mode: %s iterations: %d "
284 "bufSize %d\n",
285 algStr, (unsigned)keySizeInBits, chainEnable ? "CBC" : "ECB",
286 iterations, bufSize);
287 }
288 CFAbsoluteTime start, end;
289 auto_array<uint8> buffer(bufSize), plain(bufSize);
290 auto_ptr<Security::CssmClient::Encrypt> encrypt(NULL);
291 auto_ptr<Security::CssmClient::Decrypt> decrypt(NULL);
292
293 uint8 *bp = buffer.get();
294 for(int ix=0; ix<bufSize; ix++) {
295 *bp++ = random();
296 }
297 memcpy(plain.get(), buffer.get(), bufSize);
298
299 if(verbose) {
300 printf("%d * cdsaSetupContexts", iterations);
301 }
302 fflush(stdout);
303 start = CFAbsoluteTimeGetCurrent();
304 cdsaSetupContexts(iterations, encrypt, decrypt,
305 keyAlg, encrAlg, mode, keySizeInBits, blockSizeInBits);
306 end = CFAbsoluteTimeGetCurrent();
307 if(verbose) {
308 printf(" took: %gs\n", end - start);
309 }
310
311 printf(" %d * cdsaEncrypt %d bytes", iterations, bufSize);
312 fflush(stdout);
313 start = CFAbsoluteTimeGetCurrent();
314 cdsaEncrypt(iterations, *encrypt.get(), buffer.get(), bufSize, buffer.get(),
315 chainEnable, blockSizeBytes, resetIv);
316 end = CFAbsoluteTimeGetCurrent();
317 printf(" took: %gs %.1f Kbytes/s\n", end - start,
318 (iterations * bufSize) / (end - start) / 1024.0);
319
320 if (!memcmp(buffer.get(), plain.get(), bufSize))
321 printf("*** ciphertext matches plaintext ***\n");
322
323 printf(" %d * cdsaDecrypt %d bytes", iterations, bufSize);
324 fflush(stdout);
325 start = CFAbsoluteTimeGetCurrent();
326 cdsaDecrypt(iterations, *decrypt.get(), buffer.get(), bufSize, buffer.get(),
327 chainEnable, blockSizeBytes, resetIv);
328 end = CFAbsoluteTimeGetCurrent();
329 printf(" took: %gs %.1f Kbytes/s\n", end - start,
330 (iterations * bufSize) / (end - start) / 1024.0);
331
332 if (memcmp(buffer.get(), plain.get(), bufSize))
333 printf("*** plaintext not recovered correctly ***\n");
334 /*
335 else
336 printf("plaintext recovered\n");
337 */
338 return 0;
339 }