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 */ 47typedef 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 63static 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 */ 90static 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 */ 125static 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 */ 158static 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 */ 237static 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 */ 306static 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 412static 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 } 549abort: 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 563int 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 995testDone: 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 1011