]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ccSymCompat/ccSymCompat.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / ccSymCompat / ccSymCompat.c
1 /*
2 * ccSymCompat.c - test compatibilty of two different implementations of a
3 * given symmetric encryption algorithm - one in CommonCrypto (which we
4 * might link against directly, not using libSystem, via Makefile tweaking),
5 * the other in either libcrypto (for Blowfish and CAST), BSAFE, or the
6 * NIST reference port for AES.
7 *
8 * Written by Doug Mitchell.
9 */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <time.h>
14 #include <Security/cssm.h>
15 #include <Security/cssmapple.h>
16 #include "cspwrap.h"
17 #include "common.h"
18 #include "bsafeUtils.h"
19 #include "ssleayUtils.h"
20 #include "rijndaelApi.h"
21 #include <string.h>
22 #include <CommonCrypto/CommonCryptor.h>
23
24 /*
25 * Defaults.
26 */
27 #define LOOPS_DEF 200
28
29 #define MIN_DATA_SIZE 8
30 #define MAX_DATA_SIZE 10000 /* bytes */
31 #define MAX_KEY_SIZE MAX_KEY_SIZE_RC245_BYTES /* bytes */
32 #define LOOP_NOTIFY 20
33
34 #define NO_PAD_MODE CSSM_ALGMODE_ECB /* doesn't work for BSAFE */
35 #define NO_PAD_MODE_BSAFE CSSM_ALGMODE_CBC_IV8
36
37 /*
38 * Enumerate algs our own way to allow iteration.
39 */
40 typedef enum {
41 ALG_AES_128 = 1, /* 128 bit block, 128 bit key */
42 ALG_AES_192, /* 128 bit block, 192 bit key */
43 ALG_AES_256, /* 128 bit block, 256 bit key */
44 ALG_DES,
45 ALG_3DES,
46 ALG_CAST,
47 ALG_RC4,
48 /* not supported by CommonCrypto */
49 ALG_RC2,
50 ALG_RC5,
51 ALG_BFISH
52 } SymAlg;
53 #define ALG_FIRST ALG_AES_128
54 #define ALG_LAST ALG_RC4
55
56 static void usage(char **argv)
57 {
58 printf("usage: %s [options]\n", argv[0]);
59 printf(" Options:\n");
60 printf(" a=algorithm (d=DES; 3=3DES3; a=AES128; n=AES192; A=AES256; c=CAST;\n");
61 printf(" 4=RC4; default=all)\n");
62 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
63 printf(" k=keySizeInBits\n");
64 printf(" e(ncrypt only)\n");
65 printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE);
66 printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE);
67 printf(" p=pauseInterval (default=0, no pause)\n");
68 printf(" s (all ops single-shot, not staged)\n");
69 printf(" o (no padding, disable CBC if possible)\n");
70 printf(" z (keys and plaintext all zeroes)\n");
71 printf(" v(erbose)\n");
72 printf(" q(uiet)\n");
73 printf(" h(elp)\n");
74 exit(1);
75 }
76
77 /*
78 * encrypt/decrypt using reference BSAFE.
79 */
80 static CSSM_RETURN encryptDecryptBSAFE(
81 CSSM_BOOL forEncrypt,
82 CSSM_ALGORITHMS encrAlg,
83 CSSM_ENCRYPT_MODE encrMode,
84 const CSSM_DATA *iv, //Êoptional per mode
85 uint32 keySizeInBits,
86 uint32 effectiveKeyBits, // optional per key alg
87 uint32 rounds, // ditto
88 const CSSM_DATA *key, // raw key bytes
89 const CSSM_DATA *inText,
90 CSSM_DATA_PTR outText) // mallocd and returned
91 {
92 CSSM_RETURN crtn;
93 BU_KEY buKey;
94
95 crtn = buGenSymKey(keySizeInBits, key, &buKey);
96 if(crtn) {
97 return crtn;
98 }
99 crtn = buEncryptDecrypt(buKey,
100 forEncrypt, // forEncrypt
101 encrAlg,
102 encrMode,
103 iv,
104 effectiveKeyBits,
105 rounds,
106 inText,
107 outText);
108 buFreeKey(buKey);
109 return crtn;
110 }
111
112 /*
113 * encrypt/decrypt using reference ssleay.
114 */
115 static CSSM_RETURN encryptDecryptEAY(
116 CSSM_BOOL forEncrypt,
117 CSSM_ALGORITHMS encrAlg,
118 CSSM_ENCRYPT_MODE encrMode,
119 const CSSM_DATA *iv, // optional per mode
120 uint32 keySizeInBits,
121 const CSSM_DATA *key, // raw key bytes, Length ignored
122 const CSSM_DATA *inText,
123 CSSM_DATA_PTR outText) // mallocd and returned
124 {
125 CSSM_RETURN crtn;
126 EAY_KEY eayKey;
127 CSSM_DATA ckey = *key;
128 ckey.Length = keySizeInBits / 8;
129
130 crtn = eayGenSymKey(encrAlg, forEncrypt, &ckey, &eayKey);
131 if(crtn) {
132 return crtn;
133 }
134 crtn = eayEncryptDecrypt(eayKey,
135 forEncrypt,
136 encrAlg,
137 encrMode,
138 iv,
139 inText,
140 outText);
141 eayFreeKey(eayKey);
142 return crtn;
143 }
144
145 /*
146 * encrypt/decrypt using reference AES.
147 */
148 static CSSM_RETURN encryptDecryptAES(
149 CSSM_BOOL forEncrypt,
150 CSSM_ALGORITHMS encrAlg,
151 CSSM_ENCRYPT_MODE encrMode,
152 const CSSM_DATA *iv, //Êoptional per mode
153 uint32 keySizeInBits,
154 uint32 effectiveKeyBits, // optional per key alg
155 uint32 cipherBlockSize,
156 uint32 rounds, // ditto
157 const CSSM_DATA *key, // raw key bytes
158 const CSSM_DATA *inText,
159 CSSM_DATA_PTR outText) // mallocd and returned
160 {
161 keyInstance aesKey;
162 cipherInstance aesCipher;
163 BYTE mode;
164 int artn;
165 BYTE *ivPtr;
166
167 if(cipherBlockSize == 0) {
168 cipherBlockSize = MIN_AES_BLOCK_BITS;
169 }
170 switch(encrMode) {
171 case CSSM_ALGMODE_CBC_IV8:
172 mode = MODE_CBC;
173 ivPtr = iv->Data;
174 break;
175 case CSSM_ALGMODE_ECB:
176 mode = MODE_ECB;
177 ivPtr = NULL;
178 break;
179 default:
180 printf("***AES reference implementation doesn't do padding (yet)\n");
181 return CSSM_OK;
182 }
183 /* fixme - adjust for padding if necessary */
184 outText->Data = (uint8 *)CSSM_MALLOC(inText->Length);
185 outText->Length = inText->Length;
186 artn = _makeKey(&aesKey,
187 forEncrypt ? DIR_ENCRYPT : DIR_DECRYPT,
188 keySizeInBits,
189 cipherBlockSize,
190 key->Data);
191 if(artn <= 0) {
192 printf("***AES makeKey returned %d\n", artn);
193 return CSSM_ERRCODE_INTERNAL_ERROR;
194 }
195 artn = _cipherInit(&aesCipher,
196 mode,
197 cipherBlockSize,
198 ivPtr);
199 if(artn <= 0) {
200 printf("***AES cipherInit returned %d\n", artn);
201 return CSSM_ERRCODE_INTERNAL_ERROR;
202 }
203 if(forEncrypt) {
204 artn = _blockEncrypt(&aesCipher,
205 &aesKey,
206 (BYTE *)inText->Data,
207 inText->Length * 8,
208 (BYTE *)outText->Data);
209 }
210 else {
211 artn = _blockDecrypt(&aesCipher,
212 &aesKey,
213 (BYTE *)inText->Data,
214 inText->Length * 8,
215 (BYTE *)outText->Data);
216 }
217 if(artn <= 0) {
218 printf("***AES encrypt/decrypt returned %d\n", artn);
219 return CSSM_ERRCODE_INTERNAL_ERROR;
220 }
221 return CSSM_OK;
222 }
223
224 /*
225 * Encrypt/decrypt, one-shot, using one of the various reference implementations.
226 */
227 static CSSM_RETURN encryptDecryptRef(
228 CSSM_BOOL forEncrypt,
229 CSSM_ALGORITHMS encrAlg,
230 CSSM_ENCRYPT_MODE encrMode,
231 const CSSM_DATA *iv, // optional per mode
232 uint32 keySizeInBits,
233 uint32 effectiveKeyBits, // optional per key alg
234 uint32 cipherBlockSize,
235 uint32 rounds, // ditto
236 const CSSM_DATA *key, // raw key bytes
237 const CSSM_DATA *inText,
238 CSSM_DATA_PTR outText) // mallocd and returned
239 {
240 switch(encrAlg) {
241 case CSSM_ALGID_AES:
242 return encryptDecryptAES(
243 forEncrypt,
244 encrAlg,
245 encrMode,
246 iv,
247 keySizeInBits,
248 effectiveKeyBits,
249 cipherBlockSize,
250 rounds,
251 key,
252 inText,
253 outText);
254 case CSSM_ALGID_BLOWFISH:
255 case CSSM_ALGID_CAST:
256 return encryptDecryptEAY(
257 forEncrypt,
258 encrAlg,
259 encrMode,
260 iv,
261 keySizeInBits,
262 key,
263 inText,
264 outText);
265 default:
266 return encryptDecryptBSAFE(
267 forEncrypt,
268 encrAlg,
269 encrMode,
270 iv,
271 keySizeInBits,
272 effectiveKeyBits,
273 rounds,
274 key,
275 inText,
276 outText);
277 }
278 }
279
280 /*
281 * encrypt/decrypt using CommonCrypto.
282 */
283 static CSSM_RETURN encryptDecryptCC(
284 CSSM_BOOL forEncrypt,
285 CSSM_ALGORITHMS encrAlg,
286 CSSM_ENCRYPT_MODE encrMode,
287 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
288 uint32 cipherBlockSize,
289 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
290 const CSSM_DATA *iv, // optional per mode
291 uint32 keySizeInBits,
292 const CSSM_DATA *key, // raw key bytes
293 const CSSM_DATA *inText,
294 CSSM_DATA_PTR outText) // mallocd and returned
295 {
296 CCCryptorRef cryptor = NULL;
297 uint8 *intext = inText->Data;
298 uint32 intextLen = inText->Length;
299 uint8 *outtext;
300 size_t outtextLen; /* mallocd size of outtext */
301 size_t outBytes = 0; /* bytes actually produced in outtext */
302 CCCryptorStatus crtn;
303 uint32 blockSize;
304
305 /* convert crypt params from CDSA to CommonCrypto */
306 CCAlgorithm ccAlg;
307 CCOperation ccOp = forEncrypt ? kCCEncrypt : kCCDecrypt;
308 CCOptions ccOpts = 0;
309 uint8 *ccIv = NULL;
310
311 switch(encrAlg) {
312 case CSSM_ALGID_DES:
313 ccAlg = kCCAlgorithmDES;
314 blockSize = kCCBlockSizeDES;
315 break;
316 case CSSM_ALGID_3DES_3KEY_EDE:
317 ccAlg = kCCAlgorithm3DES;
318 blockSize = kCCBlockSize3DES;
319 break;
320 case CSSM_ALGID_AES:
321 ccAlg = kCCAlgorithmAES128;
322 blockSize = kCCBlockSizeAES128;
323 break;
324 case CSSM_ALGID_CAST:
325 ccAlg = kCCAlgorithmCAST;
326 blockSize = kCCBlockSizeCAST;
327 break;
328 case CSSM_ALGID_RC4:
329 ccAlg = kCCAlgorithmRC4;
330 blockSize = 0;
331 break;
332 default:
333 printf("***BRRZAP! Unknown algorithm in encryptDecryptCC()\n");
334 return -1;
335 }
336 if(padding != CSSM_PADDING_NONE) {
337 ccOpts |= kCCOptionPKCS7Padding;
338 }
339 switch(encrMode) {
340 case CSSM_ALGMODE_CBC_IV8:
341 /* testing DES against BSAFE */
342 ccOpts = 0;
343 ccIv = iv->Data;
344 break;
345 case CSSM_ALGMODE_ECB:
346 ccIv = NULL;
347 break;
348 case CSSM_ALGMODE_CBCPadIV8:
349 /* padding and cbc */
350 ccIv = iv->Data;
351 break;
352 case CSSM_ALGMODE_NONE:
353 /* stream cipher */
354 ccIv = NULL;
355 ccOpts = 0;
356 break;
357 default:
358 printf("***Bad mode (%lu)\n", (unsigned long)encrMode);
359 return 1;
360 }
361 if(ccIv == NULL) {
362 ccOpts |= kCCOptionECBMode;
363 }
364
365 /* alloc outtext - round up to next cipherblock boundary for encrypt */
366 if(blockSize) {
367 unsigned blocks;
368 if(forEncrypt) {
369 blocks = (intextLen + blockSize) / blockSize;
370 }
371 else {
372 blocks = intextLen / blockSize;
373 }
374 outtextLen = blocks * blockSize;
375 }
376 else {
377 outtextLen = intextLen;
378 }
379
380 outtext = (uint8 *)CSSM_MALLOC(outtextLen);
381 memset(outtext, 0x55, outtextLen);
382
383 if(!multiUpdates) {
384 /* one shot */
385 crtn = CCCrypt(ccOp, ccAlg, ccOpts,
386 key->Data, keySizeInBits / 8, ccIv,
387 intext, intextLen,
388 outtext, outtextLen, &outtextLen);
389 if(crtn) {
390 printf("***CCCrypt returned %ld\n", (long)crtn);
391 return crtn;
392 }
393 outText->Data = outtext;
394 outText->Length = outtextLen;
395 return kCCSuccess;
396 }
397
398 /* staged, random sized updates */
399 crtn = CCCryptorCreate(ccOp, ccAlg, ccOpts,
400 key->Data, keySizeInBits / 8, ccIv,
401 &cryptor);
402 if(crtn) {
403 printf("***CCCryptorInit returned %ld\n", (long)crtn);
404 return crtn;
405 }
406
407 size_t toMove = intextLen; /* total to go */
408 size_t thisMoveOut; /* output from CCCryptUpdate()/CCCryptFinal() */
409 uint8 *outp = outtext;
410 uint8 *inp = intext;
411
412 while(toMove) {
413 uint32 thisMoveIn; /* input to CCryptUpdate() */
414
415 thisMoveIn = genRand(1, toMove);
416 crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn,
417 outp, outtextLen, &thisMoveOut);
418 if(crtn) {
419 printf("***CCCryptorUpdate returned %ld\n", (long)crtn);
420 goto errOut;
421 }
422 inp += thisMoveIn;
423 toMove -= thisMoveIn;
424 outp += thisMoveOut;
425 outtextLen -= thisMoveOut;
426 outBytes += thisMoveOut;
427 }
428 crtn = CCCryptorFinal(cryptor, outp, outtextLen, &thisMoveOut);
429 if(crtn) {
430 printf("***CCCryptorFinal returned %ld\n", (long)crtn);
431 goto errOut;
432 }
433 outBytes += thisMoveOut;
434 outText->Data = outtext;
435 outText->Length = outBytes;
436 crtn = kCCSuccess;
437 errOut:
438 if(cryptor) {
439 CCCryptorRelease(cryptor);
440 }
441 return crtn;
442 }
443
444 #define LOG_FREQ 20
445
446 static int doTest(
447 const CSSM_DATA *ptext,
448 const CSSM_DATA *keyData,
449 const CSSM_DATA *iv,
450 uint32 keyAlg, // CSSM_ALGID_xxx of the key
451 uint32 encrAlg, // encrypt/decrypt
452 uint32 encrMode,
453 uint32 padding,
454 uint32 keySizeInBits,
455 uint32 efectiveKeySizeInBits,
456 uint32 cipherBlockSize,
457 CSSM_BOOL stagedEncr,
458 CSSM_BOOL stagedDecr,
459 CSSM_BOOL quiet,
460 CSSM_BOOL encryptOnly)
461 {
462 CSSM_DATA ctextRef = {0, NULL}; // ciphertext, reference
463 CSSM_DATA ctextTest = {0, NULL}; // ciphertext, test
464 CSSM_DATA rptext = {0, NULL}; // recovered plaintext
465 int rtn = 0;
466 CSSM_RETURN crtn;
467 uint32 rounds = 0;
468
469 if(encrAlg == CSSM_ALGID_RC5) {
470 /* roll the dice, pick one of three values for rounds */
471 unsigned die = genRand(1,3);
472 switch(die) {
473 case 1:
474 rounds = 8;
475 break;
476 case 2:
477 rounds = 12;
478 break;
479 case 3:
480 rounds = 16;
481 break;
482 }
483 }
484
485 /*
486 * encrypt with each method;
487 * verify ciphertexts compare;
488 * decrypt with test code;
489 * verify recovered plaintext and incoming plaintext compare;
490 */
491 crtn = encryptDecryptRef(CSSM_TRUE,
492 encrAlg,
493 encrMode,
494 iv,
495 keySizeInBits,
496 efectiveKeySizeInBits,
497 cipherBlockSize,
498 rounds,
499 keyData,
500 ptext,
501 &ctextRef);
502 if(crtn) {
503 return testError(quiet);
504 }
505 crtn = encryptDecryptCC(CSSM_TRUE,
506 encrAlg,
507 encrMode,
508 padding,
509 cipherBlockSize,
510 stagedEncr,
511 iv,
512 keySizeInBits,
513 keyData,
514 ptext,
515 &ctextTest);
516 if(crtn) {
517 return testError(quiet);
518 }
519
520 /* ensure both methods resulted in same ciphertext */
521 if(ctextRef.Length != ctextTest.Length) {
522 printf("Ctext length mismatch (1)\n");
523 rtn = testError(quiet);
524 if(rtn) {
525 goto abort;
526 }
527 }
528 if(memcmp(ctextRef.Data, ctextTest.Data, ctextTest.Length)) {
529 printf("Ctext miscompare\n");
530 rtn = testError(quiet);
531 if(rtn) {
532 goto abort;
533 }
534 }
535
536 if(encryptOnly) {
537 rtn = 0;
538 goto abort;
539 }
540
541 /* decrypt with the test method */
542 crtn = encryptDecryptCC(CSSM_FALSE,
543 encrAlg,
544 encrMode,
545 padding,
546 cipherBlockSize,
547 stagedDecr,
548 iv,
549 keySizeInBits,
550 keyData,
551 &ctextTest,
552 &rptext);
553 if(crtn) {
554 return testError(quiet);
555 }
556 if(rptext.Length != ptext->Length) {
557 printf("ptext length mismatch (1)\n");
558 rtn = testError(quiet);
559 if(rtn) {
560 goto abort;
561 }
562 }
563 if(memcmp(rptext.Data, ptext->Data, ptext->Length)) {
564 printf("ptext miscompare\n");
565 const unsigned char *cp = (const unsigned char *)rptext.Data;
566 printf("rptext %p: %02X %02X %02X %02X...\n",
567 cp, cp[0], cp[1], cp[2], cp[3]);
568 rtn = testError(quiet);
569 }
570 else {
571 rtn = 0;
572 }
573 abort:
574 if(ctextTest.Data) {
575 CSSM_FREE(ctextTest.Data);
576 }
577 if(ctextRef.Length) {
578 CSSM_FREE(ctextRef.Data);
579 }
580 if(rptext.Length) {
581 CSSM_FREE(rptext.Data);
582 }
583 return rtn;
584 }
585
586
587 int main(int argc, char **argv)
588 {
589 int arg;
590 char *argp;
591 unsigned loop;
592 CSSM_DATA ptext;
593 CSSM_BOOL stagedEncr;
594 CSSM_BOOL stagedDecr;
595 const char *algStr;
596 uint32 keyAlg; // CSSM_ALGID_xxx of the key
597 uint32 encrAlg; // CSSM_ALGID_xxx of encr/decr
598 int i;
599 unsigned currAlg; // ALG_xxx
600 uint32 actKeySizeInBits;
601 uint32 effectKeySizeInBits;
602 int rtn = 0;
603 uint32 blockSize; // for noPadding case
604 CSSM_DATA keyData;
605 CSSM_DATA initVector;
606 uint32 minTextSize;
607
608 /*
609 * User-spec'd params
610 */
611 CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size
612 unsigned minAlg = ALG_FIRST;
613 unsigned maxAlg = ALG_LAST;
614 unsigned loops = LOOPS_DEF;
615 CSSM_BOOL verbose = CSSM_FALSE;
616 CSSM_BOOL quiet = CSSM_FALSE;
617 unsigned pauseInterval = 0;
618 uint32 mode;
619 uint32 padding;
620 CSSM_BOOL noPadding = CSSM_FALSE;
621 CSSM_BOOL encryptOnly = CSSM_FALSE;
622 uint32 cipherBlockSize = 0; // AES only, bits, 0 ==> default
623 unsigned maxPtextSize = MAX_DATA_SIZE;
624 unsigned minPtextSize = MIN_DATA_SIZE;
625 CSSM_BOOL oneShotOnly = CSSM_FALSE;
626 CSSM_BOOL allZeroes = CSSM_FALSE;
627
628 for(arg=1; arg<argc; arg++) {
629 argp = argv[arg];
630 switch(argp[0]) {
631 case 'a':
632 if(argp[1] != '=') {
633 usage(argv);
634 }
635 switch(argp[2]) {
636 #if 0
637 case 's':
638 minAlg = maxAlg = ALG_ASC;
639 break;
640 #endif
641 case 'd':
642 minAlg = maxAlg = ALG_DES;
643 break;
644 case '3':
645 minAlg = maxAlg = ALG_3DES;
646 break;
647 case '2':
648 minAlg = maxAlg = ALG_RC2;
649 break;
650 case '4':
651 minAlg = maxAlg = ALG_RC4;
652 break;
653 case '5':
654 minAlg = maxAlg = ALG_RC5;
655 break;
656 case 'a':
657 minAlg = maxAlg = ALG_AES_128;
658 break;
659 case 'n':
660 minAlg = maxAlg = ALG_AES_192;
661 noPadding = CSSM_TRUE; // current restriction in
662 // our reference implementation
663 break;
664 case 'A':
665 minAlg = maxAlg = ALG_AES_256;
666 noPadding = CSSM_TRUE; // current restriction in
667 // our reference implementation
668 break;
669 case 'b':
670 minAlg = maxAlg = ALG_BFISH;
671 noPadding = CSSM_TRUE;
672 break;
673 case 'c':
674 minAlg = maxAlg = ALG_CAST;
675 noPadding = CSSM_TRUE;
676 break;
677 default:
678 usage(argv);
679 }
680 break;
681 case 'l':
682 loops = atoi(&argp[2]);
683 break;
684 case 'k':
685 actKeySizeInBits = effectKeySizeInBits = atoi(&argp[2]);
686 keySizeSpec = CSSM_TRUE;
687 break;
688 case 'b':
689 cipherBlockSize = atoi(&argp[2]);
690 break;
691 case 's':
692 oneShotOnly = CSSM_TRUE;
693 break;
694 case 'v':
695 verbose = CSSM_TRUE;
696 break;
697 case 'e':
698 encryptOnly = CSSM_TRUE;
699 break;
700 case 'm':
701 maxPtextSize = atoi(&argp[2]);
702 break;
703 case 'n':
704 minPtextSize = atoi(&argp[2]);
705 break;
706 case 'q':
707 quiet = CSSM_TRUE;
708 break;
709 case 'z':
710 allZeroes = CSSM_TRUE;
711 break;
712 case 'p':
713 pauseInterval = atoi(&argp[2]);;
714 break;
715 case 'o':
716 noPadding = CSSM_TRUE;
717 break;
718 case 'h':
719 default:
720 usage(argv);
721 }
722 }
723 ptext.Data = (uint8 *)CSSM_MALLOC(maxPtextSize);
724 if(ptext.Data == NULL) {
725 printf("Insufficient heap space\n");
726 exit(1);
727 }
728 /* ptext length set in test loop */
729
730 keyData.Data = (uint8 *)CSSM_MALLOC(MAX_KEY_SIZE);
731 if(keyData.Data == NULL) {
732 printf("Insufficient heap space\n");
733 exit(1);
734 }
735 keyData.Length = MAX_KEY_SIZE;
736
737 initVector.Data = (uint8 *)"someStrangeInitVect";
738
739 printf("Starting ccSymCompat; args: ");
740 for(i=1; i<argc; i++) {
741 printf("%s ", argv[i]);
742 }
743 printf("\n");
744 if(pauseInterval) {
745 fpurge(stdin);
746 printf("Top of test; hit CR to proceed: ");
747 getchar();
748 }
749 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
750 /* some default values... */
751 mode = CSSM_ALGMODE_NONE;
752 padding = CSSM_PADDING_NONE;
753 const char *padStr = "Off";
754 const char *modeStr = "None";
755
756 blockSize = 0; // i.e., don't align
757 switch(currAlg) {
758 case ALG_DES:
759 encrAlg = keyAlg = CSSM_ALGID_DES;
760 algStr = "DES";
761 if(noPadding) {
762 mode = NO_PAD_MODE_BSAFE;
763 modeStr = "CBC";
764 blockSize = 8;
765 }
766 else {
767 mode = CSSM_ALGMODE_CBCPadIV8;
768 modeStr = "CBC";
769 padStr = "Off";
770 padding = CSSM_PADDING_PKCS1;
771 }
772 break;
773 case ALG_3DES:
774 /* currently the only one with different key and encr algs */
775 keyAlg = CSSM_ALGID_3DES_3KEY;
776 encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
777 algStr = "3DES";
778 if(noPadding) {
779 mode = NO_PAD_MODE_BSAFE;
780 modeStr = "CBC";
781 blockSize = 8;
782 }
783 else {
784 mode = CSSM_ALGMODE_CBCPadIV8;
785 padding = CSSM_PADDING_PKCS1;
786 modeStr = "CBC";
787 padStr = "On";
788 }
789 break;
790 case ALG_RC2:
791 encrAlg = keyAlg = CSSM_ALGID_RC2;
792 algStr = "RC2";
793 if(noPadding) {
794 mode = NO_PAD_MODE_BSAFE;
795 modeStr = "CBC";
796 blockSize = 8;
797 }
798 else {
799 mode = CSSM_ALGMODE_CBCPadIV8;
800 padding = CSSM_PADDING_PKCS1; // what does padding do here?
801 modeStr = "CBC";
802 padStr = "On";
803 }
804 break;
805 case ALG_RC4:
806 encrAlg = keyAlg = CSSM_ALGID_RC4;
807 algStr = "RC4";
808 mode = CSSM_ALGMODE_NONE;
809 break;
810 case ALG_RC5:
811 encrAlg = keyAlg = CSSM_ALGID_RC5;
812 algStr = "RC5";
813 if(noPadding) {
814 mode = NO_PAD_MODE_BSAFE;
815 modeStr = "CBC";
816 blockSize = 8;
817 }
818 else {
819 mode = CSSM_ALGMODE_CBCPadIV8;
820 padding = CSSM_PADDING_PKCS1; // eh?
821 modeStr = "CBC";
822 padStr = "On";
823 }
824 break;
825 case ALG_AES_128:
826 encrAlg = keyAlg = CSSM_ALGID_AES;
827 algStr = "AES128";
828 /* padding not supported in ref implementation */
829 blockSize = 16;
830 padStr = "Off";
831 if(noPadding) {
832 /* also means no CBC */
833 mode = CSSM_ALGMODE_ECB;
834 modeStr = "ECB";
835 }
836 else {
837 mode = CSSM_ALGMODE_CBC_IV8;
838 modeStr = "CBC";
839 padStr = "Off";
840 }
841 effectKeySizeInBits = actKeySizeInBits = kCCKeySizeAES128 * 8;
842 break;
843 case ALG_AES_192:
844 encrAlg = keyAlg = CSSM_ALGID_AES;
845 algStr = "AES192";
846 mode = NO_PAD_MODE;
847 /* padding not supported in ref implementation */
848 blockSize = 16;
849 padStr = "Off";
850 if(noPadding) {
851 /* also means no CBC */
852 mode = CSSM_ALGMODE_ECB;
853 modeStr = "ECB";
854 }
855 else {
856 mode = CSSM_ALGMODE_CBC_IV8;
857 modeStr = "CBC";
858 padStr = "Off";
859 }
860 effectKeySizeInBits = actKeySizeInBits = kCCKeySizeAES192 * 8;
861 break;
862 case ALG_AES_256:
863 encrAlg = keyAlg = CSSM_ALGID_AES;
864 algStr = "AES256";
865 mode = NO_PAD_MODE;
866 /* padding not supported in ref implementation */
867 blockSize = 16;
868 padStr = "Off";
869 if(noPadding) {
870 /* also means no CBC */
871 mode = CSSM_ALGMODE_ECB;
872 modeStr = "ECB";
873 }
874 else {
875 mode = CSSM_ALGMODE_CBC_IV8;
876 modeStr = "CBC";
877 padStr = "Off";
878 }
879 effectKeySizeInBits = actKeySizeInBits = kCCKeySizeAES256 * 8;
880 break;
881 case ALG_BFISH:
882 encrAlg = keyAlg = CSSM_ALGID_BLOWFISH;
883 algStr = "Blowfish";
884 /* libcrypt doesn't do padding */
885 mode = CSSM_ALGMODE_CBC_IV8;
886 blockSize = 8;
887 modeStr = "CBC";
888 break;
889 case ALG_CAST:
890 encrAlg = keyAlg = CSSM_ALGID_CAST;
891 algStr = "CAST";
892 /* libcrypt doesn't do padding */
893 mode = CSSM_ALGMODE_CBC_IV8;
894 modeStr = "CBC";
895 blockSize = 8;
896 break;
897 }
898
899 /* assume for now all algs require IV */
900 initVector.Length = blockSize ? blockSize : 8;
901
902 if(!quiet || verbose) {
903 printf("Testing alg %s\n", algStr);
904 }
905 for(loop=1; ; loop++) {
906 minTextSize = minPtextSize; // default
907 if((blockSize != 0) && (minTextSize < blockSize)) {
908 /* i.e., AES, adjust min ptext size */
909 minTextSize = blockSize;
910 }
911 simpleGenData(&ptext, minTextSize, maxPtextSize);
912 if(blockSize) {
913 /* i.e., no padding --> align ptext */
914 ptext.Length = (ptext.Length / blockSize) * blockSize;
915 }
916 if(allZeroes) {
917 memset(ptext.Data, 0, ptext.Length);
918 memset(keyData.Data, 0, MAX_KEY_SIZE);
919 keyData.Length = MAX_KEY_SIZE;
920 }
921 else {
922 simpleGenData(&keyData, MAX_KEY_SIZE, MAX_KEY_SIZE);
923 }
924
925 if(!keySizeSpec) {
926 /*
927 * CommonCrypto's AES does one key size only
928 */
929 if(keyAlg != CSSM_ALGID_AES) {
930 effectKeySizeInBits = randKeySizeBits(keyAlg, OT_Encrypt);
931 /*
932 * generate keys with well aligned sizes; effectiveKeySize
933 * differs only if not well aligned
934 */
935 actKeySizeInBits = (effectKeySizeInBits + 7) & ~7;
936 }
937 }
938 /* else constant, spec'd by user, may be 0 (default per alg) */
939 /* mix up staging */
940 if(oneShotOnly) {
941 stagedEncr = CSSM_FALSE;
942 stagedDecr = CSSM_FALSE;
943 }
944 else {
945 stagedEncr = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
946 stagedDecr = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
947 }
948 if(!quiet) {
949 if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
950 if(cipherBlockSize) {
951 printf("..loop %d text size %lu keySizeBits %u"
952 " blockSize %u stagedEncr %d stagedDecr %d mode %s pad %s\n",
953 loop, (unsigned long)ptext.Length, (unsigned)effectKeySizeInBits,
954 (unsigned)cipherBlockSize, (int)stagedEncr, (int)stagedDecr,
955 modeStr, padStr);
956 }
957 else {
958 printf("..loop %d text size %lu keySizeBits %u"
959 " stagedEncr %d stagedDecr %d mode %s pad %s\n",
960 loop, (unsigned long)ptext.Length, (unsigned)effectKeySizeInBits,
961 (int)stagedEncr, (int)stagedDecr, modeStr, padStr);
962 }
963 }
964 }
965
966 if(doTest(&ptext,
967 &keyData,
968 &initVector,
969 keyAlg,
970 encrAlg,
971 mode,
972 padding,
973 actKeySizeInBits,
974 actKeySizeInBits, // FIXME - test effective key size
975 cipherBlockSize,
976 stagedEncr,
977 stagedDecr,
978 quiet,
979 encryptOnly)) {
980 rtn = 1;
981 break;
982 }
983 if(pauseInterval && ((loop % pauseInterval) == 0)) {
984 char c;
985 fpurge(stdin);
986 printf("Hit CR to proceed, q to abort: ");
987 c = getchar();
988 if(c == 'q') {
989 goto testDone;
990 }
991 }
992 if(loops && (loop == loops)) {
993 break;
994 }
995 } /* main loop */
996 if(rtn) {
997 break;
998 }
999
1000 } /* for algs */
1001
1002 testDone:
1003 if(pauseInterval) {
1004 fpurge(stdin);
1005 printf("ModuleDetach/Unload complete; hit CR to exit: ");
1006 getchar();
1007 }
1008 if((rtn == 0) && !quiet) {
1009 printf("%s test complete\n", argv[0]);
1010 }
1011 CSSM_FREE(ptext.Data);
1012 CSSM_FREE(keyData.Data);
1013 return rtn;
1014 }
1015
1016