1/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. 2 * 3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT 4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE 5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE 6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, 7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL 8 * EXPOSE YOU TO LIABILITY. 9 *************************************************************************** 10 * 11 * FeeFEEDExp.c - generic FEED encryption object, 2:1 expansion 12 * 13 * Revision History 14 * ---------------- 15 * 10/06/98 ap 16 * Changed to compile with C++. 17 * 20 Jan 1998 at Apple 18 * Mods for primeType == PT_GENERAL case. 19 * 12 Jun 1997 at Apple 20 * Was curveOrderJustify(), is lesserX1OrderJustify() 21 * 03 Mar 1997 at Apple 22 * Trimmed plainBlockSize by one byte if q mod 8 = 0 23 * 03 Feb 97 at NeXT 24 * Renamed to feeFEEDExp.c 25 * Justified random xaux to [2, minimumX1Order] 26 * Added feeFEEDExpCipherTextSize() 27 * 15 Jan 97 at NeXT 28 * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS 29 * 28 Aug 96 at NeXT 30 * Created from Blaine Garst's NSFEECryptor.m. 31 */ 32 33#include "ckconfig.h" 34 35#if CRYPTKIT_ASYMMETRIC_ENABLE 36 37#include "feeTypes.h" 38#include "feeFEEDExp.h" 39#include "feePublicKey.h" 40#include "feePublicKeyPrivate.h" 41#include "elliptic.h" 42#include "falloc.h" 43#include "feeRandom.h" 44#include "ckutilities.h" 45#include "feeFunctions.h" 46#include "platform.h" 47#include "feeDebug.h" 48#include <stdlib.h> 49 50#define FEED_DEBUG 0 51 52#define PRINT_GIANT(g) printGiant(g) 53 54/* 55 * Format of clue byte. Currently just one bit. 56 */ 57#define CLUE_ELL_ADD_SIGN 0x01 58#define CLUE_ELL_ADD_SIGN_PLUS 0x01 59#define CLUE_ELL_ADD_SIGN_MINUS 0x00 60 61/* 62 * Private data. 63 */ 64typedef struct { 65 key plus; 66 key minus; 67 unsigned plainBlockSize; /* plaintext block size */ 68 unsigned cipherBlockSize;/* ciphertext block size */ 69 curveParams *cp; 70 giant gPriv; /* private data, only for decrypt */ 71 /* one of the follow two is valid for encrypt */ 72 feeRand rand; /* only created for encrypt */ 73 feeRandFcn randFcn; 74 void *randRef; 75 76 /* 77 * temporary variables used for encrypt/decrypt. The values in these 78 * is not needed to be kept from block to block; we just 79 * alloc them once per lifetime of a feeFEED object as an optimization. 80 */ 81 giant xp; /* plaintext */ 82 giant xc; /* clue = r(P1?) */ 83 giant xq; /* r(pubB?) or priB?(xc) */ 84 giant xm; /* ciphertext */ 85 giant xaux; /* scratch */ 86 unsigned char *randData; /* only created for encrypt */ 87} feedInst; 88 89/* 90 * "zero residue" indicator. 91 */ 92#define RESID_ZERO 0xff 93 94/* 95 * Alloc and init a feeFEEDExp object associated with specified feePubKey. 96 */ 97feeFEEDExp feeFEEDExpNewWithPubKey( 98 feePubKey pubKey, 99 feeRandFcn randFcn, // optional 100 void *randRef) 101{ 102 feedInst *finst = (feedInst *) fmalloc(sizeof(feedInst)); 103 giant privGiant; 104 105 finst->cp = curveParamsCopy(feePubKeyCurveParams(pubKey)); 106 finst->plus = new_public_with_key(feePubKeyPlusCurve(pubKey), 107 finst->cp); 108 finst->minus = new_public_with_key(feePubKeyMinusCurve(pubKey), 109 finst->cp); 110 111 /* 112 * These might yield NULL data; we can only encrypt in that case. 113 */ 114 privGiant = feePubKeyPrivData(pubKey); 115 if(privGiant) { 116 finst->gPriv = newGiant(finst->cp->maxDigits); 117 gtog(privGiant, finst->gPriv); 118 } 119 else { 120 finst->gPriv = NULL; 121 } 122 123 /* 124 * Conservative, rounding down, on plaintext blocks since we don't 125 * want to split bytes. 126 */ 127 if(finst->cp->primeType == FPT_General) { 128 unsigned blen = bitlen(finst->cp->basePrime); 129 130 finst->plainBlockSize = blen / 8; 131 if((blen % 8) == 0) { 132 /* 133 * round down some more... 134 */ 135 finst->plainBlockSize--; 136 } 137 } 138 else { 139 finst->plainBlockSize = finst->cp->q / 8; 140 if(((finst->cp->q & 0x7) == 0) && (finst->cp->k > 0)) { 141 /* 142 * Special case, with q mod 8 == 0. Here we have to trim back 143 * the plainBlockSize by one byte. 144 */ 145 finst->plainBlockSize--; 146 } 147 } 148 149 /* 150 * One block of ciphertext - two giants (with implied sign) and a 151 * parity byte 152 */ 153 finst->cipherBlockSize = (2 * finst->cp->minBytes) + 1; 154 155 finst->xp = newGiant(finst->cp->maxDigits); 156 finst->xc = newGiant(finst->cp->maxDigits); 157 finst->xq = newGiant(finst->cp->maxDigits); 158 finst->xm = newGiant(finst->cp->maxDigits); 159 finst->xaux = newGiant(finst->cp->maxDigits); 160 finst->rand = NULL; 161 finst->randData = NULL; 162 finst->randFcn = randFcn; 163 finst->randRef = randRef; 164 return finst; 165} 166 167void feeFEEDExpFree(feeFEEDExp feed) 168{ 169 feedInst *finst = (feedInst *) feed; 170 171 free_key(finst->plus); 172 free_key(finst->minus); 173 freeGiant(finst->xc); 174 clearGiant(finst->xp); freeGiant(finst->xp); 175 clearGiant(finst->xq); freeGiant(finst->xq); 176 freeGiant(finst->xm); 177 clearGiant(finst->xaux); freeGiant(finst->xaux); 178 if(finst->gPriv) { 179 clearGiant(finst->gPriv); 180 freeGiant(finst->gPriv); 181 } 182 if(finst->rand) { 183 feeRandFree(finst->rand); 184 } 185 if(finst->randData) { 186 ffree(finst->randData); 187 } 188 if(finst->cp) { 189 freeCurveParams(finst->cp); 190 } 191 ffree(finst); 192} 193 194unsigned feeFEEDExpPlainBlockSize(feeFEEDExp feed) 195{ 196 feedInst *finst = (feedInst *) feed; 197 198 return finst->plainBlockSize; 199} 200 201unsigned feeFEEDExpCipherBlockSize(feeFEEDExp feed) 202{ 203 feedInst *finst = (feedInst *) feed; 204 205 return finst->cipherBlockSize; 206} 207 208unsigned feeFEEDExpCipherBufSize(feeFEEDExp feed) 209{ 210 feedInst *finst = (feedInst *) feed; 211 212 return 2 * finst->cipherBlockSize; 213} 214 215/* 216 * Return the size of ciphertext to hold specified size of plaintext. 217 */ 218unsigned feeFEEDExpCipherTextSize(feeFEEDExp feed, unsigned plainTextSize) 219{ 220 /* 221 * Normal case is one block of ciphertext for each block of 222 * plaintext. Add one cipherBlock if 223 * plainTextSize % plainBlockSize == 0. 224 */ 225 feedInst *finst = (feedInst *) feed; 226 unsigned blocks = (plainTextSize + finst->plainBlockSize - 1) / 227 finst->plainBlockSize; 228 229 if((plainTextSize % finst->plainBlockSize) == 0) { 230 blocks++; 231 } 232 return blocks * finst->cipherBlockSize; 233} 234 235/* 236 * Return the size of plaintext to hold specified size of decrypted ciphertext. 237 */ 238unsigned feeFEEDExpPlainTextSize(feeFEEDExp feed, unsigned cipherTextSize) 239{ 240 feedInst *finst = (feedInst *) feed; 241 unsigned blocks = (cipherTextSize + finst->cipherBlockSize - 1) / 242 finst->cipherBlockSize; 243 244 return blocks * finst->plainBlockSize; 245} 246 247/* 248 * Encrypt a block or less of data. Caller malloc's cipherText. 249 */ 250feeReturn feeFEEDExpEncryptBlock(feeFEEDExp feed, 251 const unsigned char *plainText, 252 unsigned plainTextLen, 253 unsigned char *cipherText, 254 unsigned *cipherTextLen, // RETURNED 255 int finalBlock) 256{ 257 feedInst *finst = (feedInst *) feed; 258 int index; /* which curve (+/- 1) */ 259 char g = 0; /* parity, which_curve bits in ciphertext */ 260 key B; 261 unsigned char *ptext; /* for final block */ 262 unsigned ctextLen; 263 feeReturn frtn = FR_Success; 264 giant x1; 265 unsigned randLen; 266 curveParams *cp = finst->cp; 267 268 if(plainTextLen > finst->plainBlockSize) { 269 return FR_IllegalArg; 270 } 271 else if ((plainTextLen < finst->plainBlockSize) && !finalBlock) { 272 return FR_IllegalArg; 273 } 274 275 /* 276 * Init only on first encrypt 277 */ 278 if((finst->randFcn == NULL) && (finst->rand == NULL)) { 279 finst->rand = feeRandAlloc(); 280 } 281 if(finst->randData == NULL) { 282 finst->randData = (unsigned char*) fmalloc(finst->cp->minBytes); 283 } 284 285 /* 286 * plaintext as giant xp 287 */ 288 if(finalBlock) { 289 ptext = (unsigned char*) fmalloc(finst->plainBlockSize); 290 bzero(ptext, finst->plainBlockSize); 291 if(plainTextLen) { 292 /* 293 * 0 for empty block with resid length 0 294 */ 295 bcopy(plainText, ptext, plainTextLen); 296 } 297 if(plainTextLen < finst->plainBlockSize) { 298 if(plainTextLen == 0) { 299 /* 300 * Special case - can't actually write zero here; 301 * it screws up deserializing the giant during 302 * decrypt 303 */ 304 ptext[finst->plainBlockSize - 1] = RESID_ZERO; 305 } 306 else { 307 ptext[finst->plainBlockSize - 1] = plainTextLen; 308 } 309 #if FEED_DEBUG 310 printf("encrypt: resid 0x%x\n", ptext[finst->plainBlockSize - 1]); 311 #endif 312 } 313 /* 314 * else handle evenly aligned case below... 315 */ 316 deserializeGiant(ptext, finst->xp, finst->plainBlockSize); 317 ffree(ptext); 318 } 319 else { 320 deserializeGiant(plainText, finst->xp, plainTextLen); 321 } 322 #if FEED_DEBUG 323 printf("encrypt:\n"); 324 printf(" xp : "); PRINT_GIANT(finst->xp); 325 #endif // FEED_DEBUG 326 327 /* 328 * pick curve B? that data lies upon 329 */ 330 index = which_curve(finst->xp, finst->cp); 331 if(index == CURVE_PLUS) { 332 B = finst->plus; 333 x1 = finst->cp->x1Plus; 334 } 335 else { 336 B = finst->minus; 337 x1 = finst->cp->x1Minus; 338 } 339 #if FEED_DEBUG 340 printf(" which_curve: %s\n", 341 (index == CURVE_PLUS) ? "CURVE_PLUS" : "CURVE_MINUS"); 342 #endif 343 344 /* 345 * random number as giant xaux 346 */ 347 randLen = cp->minBytes; 348 if(finst->randFcn != NULL) { 349 finst->randFcn(finst->randRef, finst->randData, randLen); 350 } 351 else { 352 feeRandBytes(finst->rand, finst->randData, randLen); 353 } 354 deserializeGiant(finst->randData, finst->xaux, randLen); 355 356 #if FEE_DEBUG 357 if(isZero(finst->xaux)) { 358 printf("feeFEEDExpEncryptBlock: random xaux = 0!\n"); 359 } 360 #endif // FEE_DEBUG 361 /* 362 * Justify random # to be in [2, minimumX1Order]. 363 */ 364 lesserX1OrderJustify(finst->xaux, cp); 365 #if FEED_DEBUG 366 printf(" xaux: "); PRINT_GIANT(finst->xaux); 367 #endif // FEED_DEBUG 368 369 gtog(B->x, finst->xq); // xq = pubB? 370 elliptic_simple(finst->xq, finst->xaux, cp); 371 // xq = r(pubB?) 372 #if FEED_DEBUG 373 printf(" r(pubB?): "); PRINT_GIANT(finst->xq); 374 #endif 375 elliptic_add(finst->xp, finst->xq, finst->xm, cp, SIGN_PLUS); 376 // xm = data + r(pubB?) 377 gtog(x1, finst->xc); 378 elliptic_simple(finst->xc, finst->xaux, cp); 379 // xc = r(P1?) 380 elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_PLUS); 381 // xaux = xm + xq (for curve +1) 382 // = (data + r(pubB?)) + r(pubB?) 383 if(gcompg(finst->xaux, finst->xp) == 0) { 384 g |= CLUE_ELL_ADD_SIGN_PLUS; 385 } 386 else { 387 g |= CLUE_ELL_ADD_SIGN_MINUS; 388 #if FEED_DEBUG 389 /* this better be true.... */ 390 elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_MINUS); 391 if(gcompg(finst->xaux, finst->xp)) { 392 printf("*******elliptic_add(xm, xq, -1) != xp! *************\n"); 393 printf(" xq : "); PRINT_GIANT(finst->xq); 394 printf(" ell_add(xm, xq, -1) : "); PRINT_GIANT(finst->xaux); 395 } 396 #endif 397 } // g = (xaux == data) ? add : subtract 398 399 /* 400 * Ciphertext = (xm, xc, g) 401 */ 402 serializeGiant(finst->xm, cipherText, cp->minBytes); 403 cipherText += cp->minBytes; 404 serializeGiant(finst->xc, cipherText, cp->minBytes); 405 cipherText += cp->minBytes; 406 *cipherText++ = g; 407 ctextLen = finst->cipherBlockSize; 408 #if FEED_DEBUG 409 printf(" xm : "); PRINT_GIANT(finst->xm); 410 printf(" xc : "); PRINT_GIANT(finst->xc); 411 printf(" g : %d\n", g); 412 #endif // FEED_DEBUG 413 if(finalBlock && (plainTextLen == finst->plainBlockSize)) { 414 /* 415 * Special case: finalBlock true, plainTextLen == blockSize. 416 * In this case we generate one more block of ciphertext, 417 * with a resid length of zero. 418 */ 419 unsigned moreCipher; // additional cipherLen 420 421 #if FEED_DEBUG 422 printf("encrypt: one more empty block\n"); 423 #endif 424 frtn = feeFEEDExpEncryptBlock(feed, 425 NULL, // plainText not used 426 0, // resid 427 cipherText, // append... 428 &moreCipher, 429 1); 430 if(frtn == FR_Success) { 431 ctextLen += moreCipher; 432 } 433 } 434 435 *cipherTextLen = ctextLen; 436 return frtn; 437} 438 439/* 440 * Decrypt (exactly) a block of data. Caller malloc's plainText. Always 441 * generates feeFEEDExpPlainBlockSize of plaintext, unless finalBlock is 442 * non-zero (in which case feeFEEDExpPlainBlockSize or less bytes of 443 * plainText are generated). 444 */ 445feeReturn feeFEEDExpDecryptBlock(feeFEEDExp feed, 446 const unsigned char *cipherText, 447 unsigned cipherTextLen, 448 unsigned char *plainText, 449 unsigned *plainTextLen, // RETURNED 450 int finalBlock) 451{ 452 feedInst *finst = (feedInst *) feed; 453 char g; 454 int s; 455 feeReturn frtn = FR_Success; 456 curveParams *cp = finst->cp; 457 458 if(finst->gPriv == NULL) { 459 /* 460 * Can't decrypt without private data 461 */ 462 return FR_BadPubKey; 463 } 464 465 /* 466 * grab xm, xc, and g from cipherText 467 */ 468 deserializeGiant(cipherText, finst->xm, finst->cp->minBytes); 469 cipherText += finst->cp->minBytes; 470 deserializeGiant(cipherText, finst->xc, finst->cp->minBytes); 471 cipherText += finst->cp->minBytes; 472 g = *cipherText; 473 #if FEED_DEBUG 474 printf("decrypt g=%d\n", g); 475 printf(" privKey : "); PRINT_GIANT(finst->gPriv); 476 printf(" xm : "); PRINT_GIANT(finst->xm); 477 printf(" xc : "); PRINT_GIANT(finst->xc); 478 #endif // FEED_DEBUG 479 480 if((g & CLUE_ELL_ADD_SIGN) == CLUE_ELL_ADD_SIGN_PLUS) { 481 s = SIGN_PLUS; 482 } 483 else { 484 s = SIGN_MINUS; 485 } 486 487 /* 488 * xc = r(P1?) 489 * xc := r(P1?)(pri) = xq 490 * xp = data + r(priB+) +/- pri(rB?) 491 */ 492 elliptic_simple(finst->xc, finst->gPriv, cp); 493 #if FEED_DEBUG 494 printf(" xc1 : "); PRINT_GIANT(finst->xc); 495 #endif 496 elliptic_add(finst->xm, finst->xc, finst->xp, cp, s); 497 498 /* 499 * plaintext in xp 500 */ 501 #if FEED_DEBUG 502 printf(" xp : "); PRINT_GIANT(finst->xp); 503 #endif // FEED_DEBUG 504 505 if(finalBlock) { 506 /* 507 * Snag data from xp in order to find out how much to move to 508 * *plainText 509 */ 510 unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize); 511 512 serializeGiant(finst->xp, ptext, finst->plainBlockSize); 513 *plainTextLen = ptext[finst->plainBlockSize - 1]; 514 #if FEED_DEBUG 515 printf("decrypt: resid 0x%x\n", *plainTextLen); 516 #endif 517 if(*plainTextLen == RESID_ZERO) { 518 *plainTextLen = 0; 519 } 520 else if(*plainTextLen > (finst->plainBlockSize - 1)) { 521 dbgLog(("feeFEEDExpDecryptBlock: ptext overflow!\n")); 522 frtn = FR_BadCipherText; 523 } 524 else { 525 bcopy(ptext, plainText, *plainTextLen); 526 } 527 ffree(ptext); 528 } 529 else { 530 *plainTextLen = finst->plainBlockSize; 531 serializeGiant(finst->xp, plainText, *plainTextLen); 532 } 533 return frtn; 534} 535 536/* 537 * Convenience routines to encrypt & decrypt multi-block data. 538 */ 539feeReturn feeFEEDExpEncrypt(feeFEEDExp feed, 540 const unsigned char *plainText, 541 unsigned plainTextLen, 542 unsigned char **cipherText, // malloc'd and RETURNED 543 unsigned *cipherTextLen) // RETURNED 544{ 545 const unsigned char *ptext; // per block 546 unsigned ptextLen; // total to go 547 unsigned thisPtextLen; // per block 548 unsigned char *ctext; // per block 549 unsigned ctextLen; // per block 550 unsigned char *ctextResult; // to return 551 unsigned ctextResultLen; 552 unsigned char *ctextPtr; 553 unsigned ctextLenTotal; // running total 554 feeReturn frtn; 555 int finalBlock; 556 unsigned numBlocks; 557 unsigned plainBlockSize; 558 559 if(plainTextLen == 0) { 560 dbgLog(("feeFEEDExpDecrypt: NULL plainText\n")); 561 return FR_IllegalArg; 562 } 563 564 ptext = plainText; 565 ptextLen = plainTextLen; 566 ctext = (unsigned char*) fmalloc(feeFEEDExpCipherBufSize(feed)); 567 plainBlockSize = feeFEEDExpPlainBlockSize(feed); 568 numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize; 569 ctextResultLen = (numBlocks + 1) * feeFEEDExpCipherBlockSize(feed); 570 ctextResult = (unsigned char*) fmalloc(ctextResultLen); 571 ctextPtr = ctextResult; 572 ctextLenTotal = 0; 573 574 while(1) { 575 if(ptextLen <= plainBlockSize) { 576 finalBlock = 1; 577 thisPtextLen = ptextLen; 578 } 579 else { 580 finalBlock = 0; 581 thisPtextLen = plainBlockSize; 582 } 583 frtn = feeFEEDExpEncryptBlock(feed, 584 ptext, 585 thisPtextLen, 586 ctext, 587 &ctextLen, 588 finalBlock); 589 if(frtn) { 590 dbgLog(("feeFEEDExpEncrypt: encrypt error: %s\n", 591 feeReturnString(frtn))); 592 break; 593 } 594 if(ctextLen == 0) { 595 dbgLog(("feeFEEDExpEncrypt: null ciphertext\n")); 596 frtn = FR_Internal; 597 break; 598 } 599 bcopy(ctext, ctextPtr, ctextLen); 600 ctextLenTotal += ctextLen; 601 if(ctextLenTotal > ctextResultLen) { 602 dbgLog(("feeFEEDExpEncrypt: ciphertext overflow\n")); 603 frtn = FR_Internal; 604 break; 605 } 606 if(finalBlock) { 607 break; 608 } 609 ctextPtr += ctextLen; 610 ptext += thisPtextLen; 611 ptextLen -= thisPtextLen; 612 } 613 614 ffree(ctext); 615 if(frtn) { 616 ffree(ctextResult); 617 *cipherText = NULL; 618 *cipherTextLen = 0; 619 } 620 else { 621 *cipherText = ctextResult; 622 *cipherTextLen = ctextLenTotal; 623 #if FEE_DEBUG 624 if(feeFEEDExpCipherTextSize(feed, plainTextLen) != 625 ctextLenTotal) { 626 printf("feeFEEDExpEncrypt: feeFEEDCipherTextSize " 627 "error!\n"); 628 printf("ptext %d exp ctext %d actual ctext %d\n", 629 plainTextLen, 630 feeFEEDExpCipherTextSize(feed, plainTextLen), 631 ctextLenTotal); 632 } 633 #endif // FEE_DEBUG 634 } 635 return frtn; 636 637} 638 639feeReturn feeFEEDExpDecrypt(feeFEEDExp feed, 640 const unsigned char *cipherText, 641 unsigned cipherTextLen, 642 unsigned char **plainText, // malloc'd and RETURNED 643 unsigned *plainTextLen) // RETURNED 644{ 645 const unsigned char *ctext; 646 unsigned ctextLen; // total to go 647 unsigned char *ptext; // per block 648 unsigned ptextLen; // per block 649 unsigned char *ptextResult; // to return 650 unsigned char *ptextPtr; 651 unsigned ptextLenTotal; // running total 652 feeReturn frtn = FR_Success; 653 int finalBlock; 654 unsigned numBlocks; 655 unsigned plainBlockSize = 656 feeFEEDExpPlainBlockSize(feed); 657 unsigned cipherBlockSize = 658 feeFEEDExpCipherBlockSize(feed); 659 660 if(cipherTextLen % cipherBlockSize) { 661 dbgLog(("feeFEEDExpDecrypt: unaligned cipherText\n")); 662 return FR_BadCipherText; 663 } 664 if(cipherTextLen == 0) { 665 dbgLog(("feeFEEDExpDecrypt: NULL cipherText\n")); 666 return FR_BadCipherText; 667 } 668 669 ptext = (unsigned char*) fmalloc(plainBlockSize); 670 ctext = cipherText; 671 ctextLen = cipherTextLen; 672 numBlocks = cipherTextLen / cipherBlockSize; 673 ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks); 674 ptextPtr = ptextResult; 675 ptextLenTotal = 0; 676 677 while(ctextLen) { 678 if(ctextLen == cipherBlockSize) { 679 finalBlock = 1; 680 } 681 else { 682 finalBlock = 0; 683 } 684 frtn = feeFEEDExpDecryptBlock(feed, 685 ctext, 686 cipherBlockSize, 687 ptext, 688 &ptextLen, 689 finalBlock); 690 if(frtn) { 691 dbgLog(("feeFEEDExpDecryptBlock: %s\n", 692 feeReturnString(frtn))); 693 break; 694 } 695 if(ptextLen == 0) { 696 /* 697 * Normal termination case for 698 * plainTextLen % plainBlockSize == 0 699 */ 700 if(!finalBlock) { 701 dbgLog(("feeFEEDExpDecrypt: decrypt sync" 702 " error!\n")); 703 frtn = FR_BadCipherText; 704 } 705 break; 706 } 707 else if(ptextLen > plainBlockSize) { 708 dbgLog(("feeFEEDExpDecrypt: ptext overflow!\n")); 709 frtn = FR_Internal; 710 break; 711 } 712 else { 713 bcopy(ptext, ptextPtr, ptextLen); 714 ptextPtr += ptextLen; 715 ptextLenTotal += ptextLen; 716 } 717 ctext += cipherBlockSize; 718 ctextLen -= cipherBlockSize; 719 } 720 721 ffree(ptext); 722 if(frtn) { 723 ffree(ptextResult); 724 *plainText = NULL; 725 *plainTextLen = 0; 726 } 727 else { 728 *plainText = ptextResult; 729 *plainTextLen = ptextLenTotal; 730 } 731 return frtn; 732 733} 734 735#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ 736