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