1/* 2 * Copyright (c) 1997,2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#include "ckutilsPlatform.h" 26#include "Crypt.h" 27#include "feeCipherFile.h" 28#include <stdlib.h> 29#include <stdio.h> 30#include <time.h> 31 32static unsigned char *dataPool; /* plaintext comes from here */ 33 34#undef BOOL 35#undef YES 36#undef NO 37#define BOOL int 38#define YES 1 39#define NO 0 40 41#define LOOPS_DEF 100 42#define MIN_EXP 2 /* for data size 10**exp */ 43#define MAX_EXP 3 /* FEED is very slow with ptext larger than this... */ 44#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT 45#define MIN_OFFSET 0 46#define MAX_OFFSET 99 47 48#define PASSWD_LENGTH 10 49 50static void usage(char **argv) 51{ 52 printf("usage: %s [options]\n", argv[0]); 53 printf("Options:\n"); 54 printf(" l==loops (default=%d)\n", LOOPS_DEF); 55 printf(" n=minExp (default=%d)\n", MIN_EXP); 56 printf(" x=maxExp (default=max=%d)\n", MAX_EXP); 57 printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); 58 printf(" N=minOffset (default=%d)\n", MIN_OFFSET); 59 printf(" q(uiet) v(erbose)\n"); 60 printf(" h(elp) I(ncrementing offset)\n"); 61 exit(1); 62} 63 64/* 65 * ...min <= return <= max 66 */ 67static int genRand(int min, int max) 68{ 69 70 /* note random() only yields a 31-bit number... */ 71 72 if(max == min) /* avoid % 1 ! */ 73 return(max); 74 else 75 return(min + (RAND() % (max-min+1))); 76} 77 78/* end of feeLib routines */ 79 80#define MIN_ASCII ' ' 81#define MAX_ASCII '~' 82 83static void genPasswd(unsigned char *passwd, 84 unsigned passwdLen, BOOL ascii) 85{ 86 unsigned *ip = (unsigned *)passwd; 87 unsigned intCount = passwdLen / 4; 88 int i; 89 unsigned char *cp; 90 unsigned residue = passwdLen & 0x3; 91 char ac; 92 93 if(ascii) { 94 cp = passwd; 95 ac = MIN_ASCII; 96 for(i=0; i<passwdLen; i++) { 97 *cp++ = ac++; 98 if(ac > MAX_ASCII) { 99 ac = MIN_ASCII; 100 } 101 } 102 } 103 else { 104 for (i=0; i<intCount; i++) { 105 *ip++ = RAND(); 106 } 107 cp = (unsigned char *)ip; 108 for(i=0; i<residue; i++) { 109 *cp = (unsigned char)RAND(); 110 } 111 } 112} 113 114/* 115 * Calculate random data size, fill dataPool with that many random bytes. 116 */ 117typedef enum { 118 DT_Random, 119 DT_Zero, 120 DT_ASCII, 121 DT_None /* data irrelevant; use existing pool */ 122} dataType; 123 124static void fillDataPool(unsigned size, dataType type) 125{ 126 #ifdef __LITTLE_ENDIAN__ 127 unsigned *ip; 128 unsigned intCount; 129 unsigned residue; 130 #endif 131 unsigned char *cp; 132 int i; 133 unsigned char ac; 134 135 switch(type) { 136 case DT_Zero: 137 bzero(dataPool, size); 138 break; 139 case DT_ASCII: 140 ac = MIN_ASCII; 141 cp = dataPool; 142 for(i=0; i<size; i++) { 143 *cp++ = ac++; 144 if(ac > MAX_ASCII) { 145 ac = MIN_ASCII; 146 } 147 } 148 break; 149 case DT_Random: 150 #ifdef __LITTLE_ENDIAN__ 151 intCount = size >> 2; 152 ip = (unsigned *)dataPool; 153 for(i=0; i<intCount; i++) { 154 *ip++ = RAND(); 155 } 156 157 residue = size & 0x3; 158 cp = (unsigned char *)ip; 159 for(i=0; i<residue; i++) { 160 *cp++ = (unsigned char)RAND(); 161 } 162 #else __LITTLE_ENDIAN__ 163 cp = dataPool; 164 for(i=0; i<size; i++) { 165 *cp++ = (char)RAND(); 166 } 167 #endif __LITTLE_ENDIAN__ 168 break; 169 case DT_None: 170 printf("fillDataPool(DT_None)\n"); 171 exit(1); 172 } 173} 174 175static unsigned dataSizeFromExp(unsigned maxExp) 176{ 177 int size = 1; 178 while(maxExp--) { // size = 10 ** exp 179 size *= 10; 180 } 181 return size; 182} 183 184static int sizeOffset = MIN_OFFSET; 185 186static unsigned char *genData(unsigned minExp, 187 unsigned maxExp, 188 dataType type, 189 BOOL incrOffset, 190 unsigned minOffset, 191 unsigned *dataLen) // RETURNED 192{ 193 int exp; 194 int offset; 195 int size; 196 197 /* 198 * Calculate "random" size : (10 ** (random exponent)) + random offset 199 */ 200 exp = genRand(minExp, maxExp); 201 if(incrOffset) { 202 offset = sizeOffset++; 203 if(sizeOffset == MAX_OFFSET) { 204 sizeOffset = minOffset; 205 } 206 } 207 else { 208 offset = genRand(minOffset, MAX_OFFSET); 209 } 210 size = dataSizeFromExp(exp) + offset; 211 if(type != DT_None) { 212 fillDataPool(size, type); 213 } 214 *dataLen = size; 215 return dataPool; 216} 217 218static feePubKey genPrivKey(const unsigned char *privKeyData, 219 unsigned privDataLen, 220 int depth) 221{ 222 feePubKey privKey; // generic key object 223 feeReturn frtn; 224 225 privKey = feePubKeyAlloc(); 226 frtn = feePubKeyInitFromPrivDataDepth(privKey, 227 (unsigned char *)privKeyData, 228 privDataLen, 229 depth, 230 1); 231 if(frtn) { 232 printf("pubKeyFromPrivDataDepth: Can't create new key (%s)\n", 233 feeReturnString(frtn)); 234 exit(1); 235 } 236 return privKey; 237} 238 239static feePubKey genPubKey(feePubKey privKey) 240{ 241 feePubKey pubKey; // generic key object 242 feeReturn frtn; 243 char *pubString; 244 unsigned pubStringLen; 245 246 frtn = feePubKeyCreateKeyString(privKey, &pubString, &pubStringLen); 247 if(frtn) { 248 printf("feePubKeyCreateKeyString: Can't get key string (%s)\n", 249 feeReturnString(frtn)); 250 exit(1); 251 } 252 pubKey = feePubKeyAlloc(); 253 frtn = feePubKeyInitFromKeyString(pubKey, pubString, pubStringLen); 254 if(frtn) { 255 printf("feePubKeyInitFromKeyString: Can't create new key " 256 "(%s)\n", 257 feeReturnString(frtn)); 258 feePubKeyFree(pubKey); 259 exit(1); 260 } 261 ffree(pubString); 262 return pubKey; 263} 264 265static char *stringFromEncrType(cipherFileEncrType encrType) 266{ 267 switch(encrType) { 268 case CFE_PublicDES: return "CFE_PublicDES"; 269 case CFE_RandDES: return "CFE_RandDES"; 270 case CFE_FEED: return "CFE_FEED"; 271 case CFE_FEEDExp: return "CFE_FEEDExp"; 272 default: return "Bogus encrType"; 273 } 274} 275 276#define SIG_NO 0 277#define SIG_YES 1 278#define EXPLICIT_NO 0 279#define EXPLICIT_YES 1 280#define EXPLICIT_ERR 2 281 282static void doTest(unsigned char *ptext, 283 unsigned ptextLen, 284 feePubKey myPrivKey, 285 feePubKey myPubKey, 286 feePubKey theirPrivKey, 287 feePubKey theirPubKey, 288 cipherFileEncrType encrType, 289 int doEnc64, 290 int doSig, 291 int doExplicitKey) /* EXPLICIT_ERR means do one with 292 * bad verify key */ 293{ 294 feeReturn frtn; 295 unsigned char *ctext; 296 unsigned ctextLen; 297 unsigned char *dectext; 298 unsigned dectextLen; 299 unsigned outUserData = 0x1234567; 300 unsigned inUserData; 301 cipherFileEncrType inEncrType; 302 feeSigStatus sigStatus; 303 int abort = 0; 304 char instr[100]; 305 feeSigStatus expSigStatus = SS_PresentValid; 306 int valid64; 307 308 /* 309 * These are tailored to specific encrTypes and doExplicitKeys 310 */ 311 feePubKey sendPrivKey = myPrivKey; 312 feePubKey sendPubKey = myPubKey; 313 feePubKey recvPrivKey = theirPrivKey; 314 feePubKey recvPubKey = theirPubKey; 315 316 switch(encrType) { 317 case CFE_RandDES: 318 case CFE_FEEDExp: 319 if(!doSig) { 320 sendPrivKey = NULL; // not needed 321 } 322 break; 323 case CFE_PublicDES: 324 case CFE_FEED: 325 break; 326 default: 327 printf("Hey bozo! Give me a real encrType!\n"); 328 exit(1); 329 } 330 if(!doSig) { 331 sendPubKey = NULL; // never needed 332 expSigStatus = SS_NotPresent; 333 } 334 else switch(doExplicitKey) { 335 case EXPLICIT_NO: 336 sendPubKey = NULL; // get it from cipherfile 337 break; 338 case EXPLICIT_YES: 339 break; // use myPubKey 340 case EXPLICIT_ERR: 341 if(feePubKeyIsEqual(myPubKey, theirPubKey)) { 342 printf("myPubKey = theirPubKey!\n"); 343 goto errOut; 344 } 345 sendPubKey = theirPubKey; // hopefully != myPubKey! 346 expSigStatus = SS_PresentInvalid; 347 break; 348 default: 349 printf("BOGUS doExplicitKey\n"); 350 exit(1); 351 } 352 353 frtn = createCipherFile(sendPrivKey, 354 recvPubKey, 355 encrType, 356 ptext, 357 ptextLen, 358 doSig, 359 doEnc64, 360 outUserData, 361 &ctext, 362 &ctextLen); 363 if(frtn) { 364 printf("createCipherFile: %s\n", feeReturnString(frtn)); 365 goto errOut; 366 } 367 368 valid64 = isValidEnc64(ctext, ctextLen); 369 if(valid64 != doEnc64) { 370 printf("valid64 mismatch! exp %d got %d\n", doEnc64, valid64); 371 abort = 1; 372 } 373 frtn = parseCipherFile(recvPrivKey, 374 sendPubKey, 375 ctext, 376 ctextLen, 377 doEnc64, 378 &inEncrType, 379 &dectext, 380 &dectextLen, 381 &sigStatus, 382 &inUserData); 383 if(frtn) { 384 printf("parseCipherFile: %s\n", feeReturnString(frtn)); 385 goto errOut; 386 } 387 if(inEncrType != encrType) { 388 printf("encrType mismatch exp %d got %d\n", 389 encrType, inEncrType); 390 abort = 1; 391 } 392 if(inUserData != outUserData) { 393 printf("userData mismatch exp %d got %d\n", 394 outUserData, inUserData); 395 abort = 1; 396 } 397 if(sigStatus != expSigStatus) { 398 printf("Bad sigStatus exp %d got %d\n", 399 expSigStatus, sigStatus); 400 abort = 1; 401 } 402 if(ptextLen != dectextLen) { 403 printf("ptextLen mismatch exp %d got %d\n", 404 ptextLen, dectextLen); 405 abort = 1; 406 } 407 if(bcmp(ptext, dectext, ptextLen)) { 408 printf("Data Miscompare\n"); 409 abort = 1; 410 } 411 ffree(dectext); 412 ffree(ctext); 413 if(!abort) { 414 return; 415 } 416errOut: 417 /* dump params */ 418 printf("attach with debugger for more info; enter CR to quit: "); 419 gets(instr); 420 exit(1); 421 422} 423 424int main(int argc, char **argv) 425{ 426 int arg; 427 char *argp; 428 int loop; 429 unsigned char *ptext; 430 unsigned ptextLen; 431 unsigned char passwd1[PASSWD_LENGTH]; 432 unsigned char passwd2[PASSWD_LENGTH]; 433 int encrType; 434 int doEnc64; 435 feePubKey myPrivKey; 436 feePubKey theirPrivKey; 437 feePubKey myPubKey; 438 feePubKey theirPubKey; 439 unsigned maxSize; 440 441 /* 442 * User-spec'd params 443 */ 444 unsigned loops = LOOPS_DEF; 445 BOOL seedSpec = NO; 446 unsigned seed; 447 BOOL quiet = NO; 448 BOOL verbose = NO; 449 unsigned minExp = MIN_EXP; 450 unsigned maxExp = MAX_EXP; 451 BOOL incrOffset = NO; 452 unsigned depth = DEPTH_DEFAULT; 453 unsigned minOffset = MIN_OFFSET; 454 455 #if macintosh 456 argc = ccommand(&argv); 457 #endif 458 459 for(arg=1; arg<argc; arg++) { 460 argp = argv[arg]; 461 switch(argp[0]) { 462 case 'l': 463 loops = atoi(&argp[2]); 464 break; 465 case 'n': 466 minExp = atoi(&argp[2]); 467 break; 468 case 'D': 469 depth = atoi(&argp[2]); 470 break; 471 case 'N': 472 minOffset = atoi(&argp[2]); 473 if(minOffset > MAX_OFFSET) { 474 minOffset = MIN_OFFSET; 475 } 476 sizeOffset = minOffset; 477 break; 478 case 'x': 479 maxExp = atoi(&argp[2]); 480 if(maxExp > MAX_EXP) { 481 usage(argv); 482 } 483 break; 484 case 's': 485 seed = atoi(&argp[2]); 486 seedSpec = YES; 487 break; 488 case 'I': 489 incrOffset = YES; 490 break; 491 case 'q': 492 quiet = YES; 493 break; 494 case 'v': 495 verbose = YES; 496 break; 497 case 'h': 498 default: 499 usage(argv); 500 } 501 } 502 503 if(seedSpec == NO) { 504 time((unsigned long *)(&seed)); 505 } 506 SRAND(seed); 507 maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8; 508 dataPool = fmalloc(maxSize); 509 510 printf("Starting cfileTest: loops %d seed %d depth %d\n", 511 loops, seed, depth); 512 513 for(loop=1; ; loop++) { 514 515 ptext = genData(minExp, maxExp, DT_Random, incrOffset, 516 minOffset, &ptextLen); 517 if(!quiet) { 518 printf("..loop %d plaintext size %d\n", loop, ptextLen); 519 } 520 521 /* 522 * Generate a whole bunch of keys 523 */ 524 genPasswd(passwd1, PASSWD_LENGTH, NO); // not ascii! 525 genPasswd(passwd2, PASSWD_LENGTH, NO); 526 myPrivKey = genPrivKey(passwd1, PASSWD_LENGTH, depth); 527 theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth); 528 myPubKey = genPubKey(myPrivKey); 529 theirPubKey = genPubKey(theirPrivKey); 530 531 for(encrType=CFE_PublicDES; 532 encrType<=CFE_FEEDExp; 533 encrType++) { 534 535 if(verbose) { 536 printf(" ..%s\n", stringFromEncrType(encrType)); 537 } 538 for(doEnc64=0; doEnc64<2; doEnc64++) { 539 if(verbose) { 540 printf(" ..doEnc64 %d\n", doEnc64); 541 } 542 543 if(verbose) { 544 printf(" ..no sig\n"); 545 } 546 doTest(ptext, ptextLen, myPrivKey, myPubKey, 547 theirPrivKey, theirPubKey, 548 encrType, doEnc64, SIG_NO, EXPLICIT_NO); 549 550 if(verbose) { 551 printf(" ..sig, implicit sendPubKey\n"); 552 } 553 doTest(ptext, ptextLen, myPrivKey, myPubKey, 554 theirPrivKey, theirPubKey, 555 encrType, doEnc64, SIG_YES, EXPLICIT_NO); 556 557 if(verbose) { 558 printf(" ..sig, explicit sendPubKey\n"); 559 } 560 doTest(ptext, ptextLen, myPrivKey, myPubKey, 561 theirPrivKey, theirPubKey, 562 encrType, doEnc64, SIG_YES, EXPLICIT_YES); 563 564 if(verbose) { 565 printf(" ..sig, force error\n"); 566 } 567 doTest(ptext, ptextLen, myPrivKey, myPubKey, 568 theirPrivKey, theirPubKey, 569 encrType, doEnc64, SIG_YES, EXPLICIT_ERR); 570 571 } /* for doEnc64 */ 572 } /* for encrType */ 573 574 feePubKeyFree(myPrivKey); 575 feePubKeyFree(myPubKey); 576 feePubKeyFree(theirPrivKey); 577 feePubKeyFree(theirPubKey); 578 if(loops) { 579 if(loop == loops) { 580 break; 581 } 582 } 583 } /* main loop */ 584 585 if(!quiet) { 586 printf("cfile test complete\n"); 587 } 588 return 0; 589} 590