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