]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/feeFEEDExp.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / lib / feeFEEDExp.c
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 */
64 typedef 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 */
97 feeFEEDExp 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
167 void 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
194 unsigned feeFEEDExpPlainBlockSize(feeFEEDExp feed)
195 {
196 feedInst *finst = (feedInst *) feed;
197
198 return finst->plainBlockSize;
199 }
200
201 unsigned feeFEEDExpCipherBlockSize(feeFEEDExp feed)
202 {
203 feedInst *finst = (feedInst *) feed;
204
205 return finst->cipherBlockSize;
206 }
207
208 unsigned 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 */
218 unsigned 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 */
238 unsigned 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 */
250 feeReturn 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 randLen = cp->minBytes+8; // +8bytes (64bits) to reduce the biais when with reduction mod prime. Per FIPS186-4 - "Using Extra Random Bits"
268
269 if(plainTextLen > finst->plainBlockSize) {
270 return FR_IllegalArg;
271 }
272 else if ((plainTextLen < finst->plainBlockSize) && !finalBlock) {
273 return FR_IllegalArg;
274 }
275
276 /*
277 * Init only on first encrypt
278 */
279 if((finst->randFcn == NULL) && (finst->rand == NULL)) {
280 finst->rand = feeRandAlloc();
281 }
282 if(finst->randData == NULL) {
283 finst->randData = (unsigned char*) fmalloc(randLen);
284 }
285
286 /*
287 * plaintext as giant xp
288 */
289 if(finalBlock) {
290 ptext = (unsigned char*) fmalloc(finst->plainBlockSize);
291 bzero(ptext, finst->plainBlockSize);
292 if(plainTextLen) {
293 /*
294 * 0 for empty block with resid length 0
295 */
296 bcopy(plainText, ptext, plainTextLen);
297 }
298 if(plainTextLen < finst->plainBlockSize) {
299 if(plainTextLen == 0) {
300 /*
301 * Special case - can't actually write zero here;
302 * it screws up deserializing the giant during
303 * decrypt
304 */
305 ptext[finst->plainBlockSize - 1] = RESID_ZERO;
306 }
307 else {
308 ptext[finst->plainBlockSize - 1] = plainTextLen;
309 }
310 #if FEED_DEBUG
311 printf("encrypt: resid 0x%x\n", ptext[finst->plainBlockSize - 1]);
312 #endif
313 }
314 /*
315 * else handle evenly aligned case below...
316 */
317 deserializeGiant(ptext, finst->xp, finst->plainBlockSize);
318 ffree(ptext);
319 }
320 else {
321 deserializeGiant(plainText, finst->xp, plainTextLen);
322 }
323 #if FEED_DEBUG
324 printf("encrypt:\n");
325 printf(" xp : "); PRINT_GIANT(finst->xp);
326 #endif // FEED_DEBUG
327
328 /*
329 * pick curve B? that data lies upon
330 */
331 index = which_curve(finst->xp, finst->cp);
332 if(index == CURVE_PLUS) {
333 B = finst->plus;
334 x1 = finst->cp->x1Plus;
335 }
336 else {
337 B = finst->minus;
338 x1 = finst->cp->x1Minus;
339 }
340 #if FEED_DEBUG
341 printf(" which_curve: %s\n",
342 (index == CURVE_PLUS) ? "CURVE_PLUS" : "CURVE_MINUS");
343 #endif
344
345 /*
346 * random number as giant xaux
347 */
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 */
445 feeReturn 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 */
539 feeReturn 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
639 feeReturn 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 */