--- /dev/null
+/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
+ *
+ * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
+ * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
+ * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
+ * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
+ * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
+ * EXPOSE YOU TO LIABILITY.
+ ***************************************************************************
+ *
+ * FeeFEEDExp.c - generic FEED encryption object, 2:1 expansion
+ *
+ * Revision History
+ * ----------------
+ * 10/06/98 ap
+ * Changed to compile with C++.
+ * 20 Jan 1998 at Apple
+ * Mods for primeType == PT_GENERAL case.
+ * 12 Jun 1997 at Apple
+ * Was curveOrderJustify(), is lesserX1OrderJustify()
+ * 03 Mar 1997 at Apple
+ * Trimmed plainBlockSize by one byte if q mod 8 = 0
+ * 03 Feb 97 at NeXT
+ * Renamed to feeFEEDExp.c
+ * Justified random xaux to [2, minimumX1Order]
+ * Added feeFEEDExpCipherTextSize()
+ * 15 Jan 97 at NeXT
+ * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS
+ * 28 Aug 96 at NeXT
+ * Created from Blaine Garst's NSFEECryptor.m.
+ */
+
+#include "ckconfig.h"
+
+#if CRYPTKIT_ASYMMETRIC_ENABLE
+
+#include "feeTypes.h"
+#include "feeFEEDExp.h"
+#include "feePublicKey.h"
+#include "feePublicKeyPrivate.h"
+#include "elliptic.h"
+#include "falloc.h"
+#include "feeRandom.h"
+#include "ckutilities.h"
+#include "feeFunctions.h"
+#include "platform.h"
+#include "feeDebug.h"
+#include <stdlib.h>
+
+#define FEED_DEBUG 0
+
+#define PRINT_GIANT(g) printGiant(g)
+
+/*
+ * Format of clue byte. Currently just one bit.
+ */
+#define CLUE_ELL_ADD_SIGN 0x01
+#define CLUE_ELL_ADD_SIGN_PLUS 0x01
+#define CLUE_ELL_ADD_SIGN_MINUS 0x00
+
+/*
+ * Private data.
+ */
+typedef struct {
+ key plus;
+ key minus;
+ unsigned plainBlockSize; /* plaintext block size */
+ unsigned cipherBlockSize;/* ciphertext block size */
+ curveParams *cp;
+ giant gPriv; /* private data, only for decrypt */
+ /* one of the follow two is valid for encrypt */
+ feeRand rand; /* only created for encrypt */
+ feeRandFcn randFcn;
+ void *randRef;
+
+ /*
+ * temporary variables used for encrypt/decrypt. The values in these
+ * is not needed to be kept from block to block; we just
+ * alloc them once per lifetime of a feeFEED object as an optimization.
+ */
+ giant xp; /* plaintext */
+ giant xc; /* clue = r(P1?) */
+ giant xq; /* r(pubB?) or priB?(xc) */
+ giant xm; /* ciphertext */
+ giant xaux; /* scratch */
+ unsigned char *randData; /* only created for encrypt */
+} feedInst;
+
+/*
+ * "zero residue" indicator.
+ */
+#define RESID_ZERO 0xff
+
+/*
+ * Alloc and init a feeFEEDExp object associated with specified feePubKey.
+ */
+feeFEEDExp feeFEEDExpNewWithPubKey(
+ feePubKey pubKey,
+ feeRandFcn randFcn, // optional
+ void *randRef)
+{
+ feedInst *finst = (feedInst *) fmalloc(sizeof(feedInst));
+ giant privGiant;
+
+ finst->cp = curveParamsCopy(feePubKeyCurveParams(pubKey));
+ finst->plus = new_public_with_key(feePubKeyPlusCurve(pubKey),
+ finst->cp);
+ finst->minus = new_public_with_key(feePubKeyMinusCurve(pubKey),
+ finst->cp);
+
+ /*
+ * These might yield NULL data; we can only encrypt in that case.
+ */
+ privGiant = feePubKeyPrivData(pubKey);
+ if(privGiant) {
+ finst->gPriv = newGiant(finst->cp->maxDigits);
+ gtog(privGiant, finst->gPriv);
+ }
+ else {
+ finst->gPriv = NULL;
+ }
+
+ /*
+ * Conservative, rounding down, on plaintext blocks since we don't
+ * want to split bytes.
+ */
+ if(finst->cp->primeType == FPT_General) {
+ unsigned blen = bitlen(finst->cp->basePrime);
+
+ finst->plainBlockSize = blen / 8;
+ if((blen % 8) == 0) {
+ /*
+ * round down some more...
+ */
+ finst->plainBlockSize--;
+ }
+ }
+ else {
+ finst->plainBlockSize = finst->cp->q / 8;
+ if(((finst->cp->q & 0x7) == 0) && (finst->cp->k > 0)) {
+ /*
+ * Special case, with q mod 8 == 0. Here we have to trim back
+ * the plainBlockSize by one byte.
+ */
+ finst->plainBlockSize--;
+ }
+ }
+
+ /*
+ * One block of ciphertext - two giants (with implied sign) and a
+ * parity byte
+ */
+ finst->cipherBlockSize = (2 * finst->cp->minBytes) + 1;
+
+ finst->xp = newGiant(finst->cp->maxDigits);
+ finst->xc = newGiant(finst->cp->maxDigits);
+ finst->xq = newGiant(finst->cp->maxDigits);
+ finst->xm = newGiant(finst->cp->maxDigits);
+ finst->xaux = newGiant(finst->cp->maxDigits);
+ finst->rand = NULL;
+ finst->randData = NULL;
+ finst->randFcn = randFcn;
+ finst->randRef = randRef;
+ return finst;
+}
+
+void feeFEEDExpFree(feeFEEDExp feed)
+{
+ feedInst *finst = (feedInst *) feed;
+
+ free_key(finst->plus);
+ free_key(finst->minus);
+ freeGiant(finst->xc);
+ clearGiant(finst->xp); freeGiant(finst->xp);
+ clearGiant(finst->xq); freeGiant(finst->xq);
+ freeGiant(finst->xm);
+ clearGiant(finst->xaux); freeGiant(finst->xaux);
+ if(finst->gPriv) {
+ clearGiant(finst->gPriv);
+ freeGiant(finst->gPriv);
+ }
+ if(finst->rand) {
+ feeRandFree(finst->rand);
+ }
+ if(finst->randData) {
+ ffree(finst->randData);
+ }
+ if(finst->cp) {
+ freeCurveParams(finst->cp);
+ }
+ ffree(finst);
+}
+
+unsigned feeFEEDExpPlainBlockSize(feeFEEDExp feed)
+{
+ feedInst *finst = (feedInst *) feed;
+
+ return finst->plainBlockSize;
+}
+
+unsigned feeFEEDExpCipherBlockSize(feeFEEDExp feed)
+{
+ feedInst *finst = (feedInst *) feed;
+
+ return finst->cipherBlockSize;
+}
+
+unsigned feeFEEDExpCipherBufSize(feeFEEDExp feed)
+{
+ feedInst *finst = (feedInst *) feed;
+
+ return 2 * finst->cipherBlockSize;
+}
+
+/*
+ * Return the size of ciphertext to hold specified size of plaintext.
+ */
+unsigned feeFEEDExpCipherTextSize(feeFEEDExp feed, unsigned plainTextSize)
+{
+ /*
+ * Normal case is one block of ciphertext for each block of
+ * plaintext. Add one cipherBlock if
+ * plainTextSize % plainBlockSize == 0.
+ */
+ feedInst *finst = (feedInst *) feed;
+ unsigned blocks = (plainTextSize + finst->plainBlockSize - 1) /
+ finst->plainBlockSize;
+
+ if((plainTextSize % finst->plainBlockSize) == 0) {
+ blocks++;
+ }
+ return blocks * finst->cipherBlockSize;
+}
+
+/*
+ * Return the size of plaintext to hold specified size of decrypted ciphertext.
+ */
+unsigned feeFEEDExpPlainTextSize(feeFEEDExp feed, unsigned cipherTextSize)
+{
+ feedInst *finst = (feedInst *) feed;
+ unsigned blocks = (cipherTextSize + finst->cipherBlockSize - 1) /
+ finst->cipherBlockSize;
+
+ return blocks * finst->plainBlockSize;
+}
+
+/*
+ * Encrypt a block or less of data. Caller malloc's cipherText.
+ */
+feeReturn feeFEEDExpEncryptBlock(feeFEEDExp feed,
+ const unsigned char *plainText,
+ unsigned plainTextLen,
+ unsigned char *cipherText,
+ unsigned *cipherTextLen, // RETURNED
+ int finalBlock)
+{
+ feedInst *finst = (feedInst *) feed;
+ int index; /* which curve (+/- 1) */
+ char g = 0; /* parity, which_curve bits in ciphertext */
+ key B;
+ unsigned char *ptext; /* for final block */
+ unsigned ctextLen;
+ feeReturn frtn = FR_Success;
+ giant x1;
+ unsigned randLen;
+ curveParams *cp = finst->cp;
+
+ if(plainTextLen > finst->plainBlockSize) {
+ return FR_IllegalArg;
+ }
+ else if ((plainTextLen < finst->plainBlockSize) && !finalBlock) {
+ return FR_IllegalArg;
+ }
+
+ /*
+ * Init only on first encrypt
+ */
+ if((finst->randFcn == NULL) && (finst->rand == NULL)) {
+ finst->rand = feeRandAlloc();
+ }
+ if(finst->randData == NULL) {
+ finst->randData = (unsigned char*) fmalloc(finst->cp->minBytes);
+ }
+
+ /*
+ * plaintext as giant xp
+ */
+ if(finalBlock) {
+ ptext = (unsigned char*) fmalloc(finst->plainBlockSize);
+ bzero(ptext, finst->plainBlockSize);
+ if(plainTextLen) {
+ /*
+ * 0 for empty block with resid length 0
+ */
+ bcopy(plainText, ptext, plainTextLen);
+ }
+ if(plainTextLen < finst->plainBlockSize) {
+ if(plainTextLen == 0) {
+ /*
+ * Special case - can't actually write zero here;
+ * it screws up deserializing the giant during
+ * decrypt
+ */
+ ptext[finst->plainBlockSize - 1] = RESID_ZERO;
+ }
+ else {
+ ptext[finst->plainBlockSize - 1] = plainTextLen;
+ }
+ #if FEED_DEBUG
+ printf("encrypt: resid 0x%x\n", ptext[finst->plainBlockSize - 1]);
+ #endif
+ }
+ /*
+ * else handle evenly aligned case below...
+ */
+ deserializeGiant(ptext, finst->xp, finst->plainBlockSize);
+ ffree(ptext);
+ }
+ else {
+ deserializeGiant(plainText, finst->xp, plainTextLen);
+ }
+ #if FEED_DEBUG
+ printf("encrypt:\n");
+ printf(" xp : "); PRINT_GIANT(finst->xp);
+ #endif // FEED_DEBUG
+
+ /*
+ * pick curve B? that data lies upon
+ */
+ index = which_curve(finst->xp, finst->cp);
+ if(index == CURVE_PLUS) {
+ B = finst->plus;
+ x1 = finst->cp->x1Plus;
+ }
+ else {
+ B = finst->minus;
+ x1 = finst->cp->x1Minus;
+ }
+ #if FEED_DEBUG
+ printf(" which_curve: %s\n",
+ (index == CURVE_PLUS) ? "CURVE_PLUS" : "CURVE_MINUS");
+ #endif
+
+ /*
+ * random number as giant xaux
+ */
+ randLen = cp->minBytes;
+ if(finst->randFcn != NULL) {
+ finst->randFcn(finst->randRef, finst->randData, randLen);
+ }
+ else {
+ feeRandBytes(finst->rand, finst->randData, randLen);
+ }
+ deserializeGiant(finst->randData, finst->xaux, randLen);
+
+ #if FEE_DEBUG
+ if(isZero(finst->xaux)) {
+ printf("feeFEEDExpEncryptBlock: random xaux = 0!\n");
+ }
+ #endif // FEE_DEBUG
+ /*
+ * Justify random # to be in [2, minimumX1Order].
+ */
+ lesserX1OrderJustify(finst->xaux, cp);
+ #if FEED_DEBUG
+ printf(" xaux: "); PRINT_GIANT(finst->xaux);
+ #endif // FEED_DEBUG
+
+ gtog(B->x, finst->xq); // xq = pubB?
+ elliptic_simple(finst->xq, finst->xaux, cp);
+ // xq = r(pubB?)
+ #if FEED_DEBUG
+ printf(" r(pubB?): "); PRINT_GIANT(finst->xq);
+ #endif
+ elliptic_add(finst->xp, finst->xq, finst->xm, cp, SIGN_PLUS);
+ // xm = data + r(pubB?)
+ gtog(x1, finst->xc);
+ elliptic_simple(finst->xc, finst->xaux, cp);
+ // xc = r(P1?)
+ elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_PLUS);
+ // xaux = xm + xq (for curve +1)
+ // = (data + r(pubB?)) + r(pubB?)
+ if(gcompg(finst->xaux, finst->xp) == 0) {
+ g |= CLUE_ELL_ADD_SIGN_PLUS;
+ }
+ else {
+ g |= CLUE_ELL_ADD_SIGN_MINUS;
+ #if FEED_DEBUG
+ /* this better be true.... */
+ elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_MINUS);
+ if(gcompg(finst->xaux, finst->xp)) {
+ printf("*******elliptic_add(xm, xq, -1) != xp! *************\n");
+ printf(" xq : "); PRINT_GIANT(finst->xq);
+ printf(" ell_add(xm, xq, -1) : "); PRINT_GIANT(finst->xaux);
+ }
+ #endif
+ } // g = (xaux == data) ? add : subtract
+
+ /*
+ * Ciphertext = (xm, xc, g)
+ */
+ serializeGiant(finst->xm, cipherText, cp->minBytes);
+ cipherText += cp->minBytes;
+ serializeGiant(finst->xc, cipherText, cp->minBytes);
+ cipherText += cp->minBytes;
+ *cipherText++ = g;
+ ctextLen = finst->cipherBlockSize;
+ #if FEED_DEBUG
+ printf(" xm : "); PRINT_GIANT(finst->xm);
+ printf(" xc : "); PRINT_GIANT(finst->xc);
+ printf(" g : %d\n", g);
+ #endif // FEED_DEBUG
+ if(finalBlock && (plainTextLen == finst->plainBlockSize)) {
+ /*
+ * Special case: finalBlock true, plainTextLen == blockSize.
+ * In this case we generate one more block of ciphertext,
+ * with a resid length of zero.
+ */
+ unsigned moreCipher; // additional cipherLen
+
+ #if FEED_DEBUG
+ printf("encrypt: one more empty block\n");
+ #endif
+ frtn = feeFEEDExpEncryptBlock(feed,
+ NULL, // plainText not used
+ 0, // resid
+ cipherText, // append...
+ &moreCipher,
+ 1);
+ if(frtn == FR_Success) {
+ ctextLen += moreCipher;
+ }
+ }
+
+ *cipherTextLen = ctextLen;
+ return frtn;
+}
+
+/*
+ * Decrypt (exactly) a block of data. Caller malloc's plainText. Always
+ * generates feeFEEDExpPlainBlockSize of plaintext, unless finalBlock is
+ * non-zero (in which case feeFEEDExpPlainBlockSize or less bytes of
+ * plainText are generated).
+ */
+feeReturn feeFEEDExpDecryptBlock(feeFEEDExp feed,
+ const unsigned char *cipherText,
+ unsigned cipherTextLen,
+ unsigned char *plainText,
+ unsigned *plainTextLen, // RETURNED
+ int finalBlock)
+{
+ feedInst *finst = (feedInst *) feed;
+ char g;
+ int s;
+ feeReturn frtn = FR_Success;
+ curveParams *cp = finst->cp;
+
+ if(finst->gPriv == NULL) {
+ /*
+ * Can't decrypt without private data
+ */
+ return FR_BadPubKey;
+ }
+
+ /*
+ * grab xm, xc, and g from cipherText
+ */
+ deserializeGiant(cipherText, finst->xm, finst->cp->minBytes);
+ cipherText += finst->cp->minBytes;
+ deserializeGiant(cipherText, finst->xc, finst->cp->minBytes);
+ cipherText += finst->cp->minBytes;
+ g = *cipherText;
+ #if FEED_DEBUG
+ printf("decrypt g=%d\n", g);
+ printf(" privKey : "); PRINT_GIANT(finst->gPriv);
+ printf(" xm : "); PRINT_GIANT(finst->xm);
+ printf(" xc : "); PRINT_GIANT(finst->xc);
+ #endif // FEED_DEBUG
+
+ if((g & CLUE_ELL_ADD_SIGN) == CLUE_ELL_ADD_SIGN_PLUS) {
+ s = SIGN_PLUS;
+ }
+ else {
+ s = SIGN_MINUS;
+ }
+
+ /*
+ * xc = r(P1?)
+ * xc := r(P1?)(pri) = xq
+ * xp = data + r(priB+) +/- pri(rB?)
+ */
+ elliptic_simple(finst->xc, finst->gPriv, cp);
+ #if FEED_DEBUG
+ printf(" xc1 : "); PRINT_GIANT(finst->xc);
+ #endif
+ elliptic_add(finst->xm, finst->xc, finst->xp, cp, s);
+
+ /*
+ * plaintext in xp
+ */
+ #if FEED_DEBUG
+ printf(" xp : "); PRINT_GIANT(finst->xp);
+ #endif // FEED_DEBUG
+
+ if(finalBlock) {
+ /*
+ * Snag data from xp in order to find out how much to move to
+ * *plainText
+ */
+ unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize);
+
+ serializeGiant(finst->xp, ptext, finst->plainBlockSize);
+ *plainTextLen = ptext[finst->plainBlockSize - 1];
+ #if FEED_DEBUG
+ printf("decrypt: resid 0x%x\n", *plainTextLen);
+ #endif
+ if(*plainTextLen == RESID_ZERO) {
+ *plainTextLen = 0;
+ }
+ else if(*plainTextLen > (finst->plainBlockSize - 1)) {
+ dbgLog(("feeFEEDExpDecryptBlock: ptext overflow!\n"));
+ frtn = FR_BadCipherText;
+ }
+ else {
+ bcopy(ptext, plainText, *plainTextLen);
+ }
+ ffree(ptext);
+ }
+ else {
+ *plainTextLen = finst->plainBlockSize;
+ serializeGiant(finst->xp, plainText, *plainTextLen);
+ }
+ return frtn;
+}
+
+/*
+ * Convenience routines to encrypt & decrypt multi-block data.
+ */
+feeReturn feeFEEDExpEncrypt(feeFEEDExp feed,
+ const unsigned char *plainText,
+ unsigned plainTextLen,
+ unsigned char **cipherText, // malloc'd and RETURNED
+ unsigned *cipherTextLen) // RETURNED
+{
+ const unsigned char *ptext; // per block
+ unsigned ptextLen; // total to go
+ unsigned thisPtextLen; // per block
+ unsigned char *ctext; // per block
+ unsigned ctextLen; // per block
+ unsigned char *ctextResult; // to return
+ unsigned ctextResultLen;
+ unsigned char *ctextPtr;
+ unsigned ctextLenTotal; // running total
+ feeReturn frtn;
+ int finalBlock;
+ unsigned numBlocks;
+ unsigned plainBlockSize;
+
+ if(plainTextLen == 0) {
+ dbgLog(("feeFEEDExpDecrypt: NULL plainText\n"));
+ return FR_IllegalArg;
+ }
+
+ ptext = plainText;
+ ptextLen = plainTextLen;
+ ctext = (unsigned char*) fmalloc(feeFEEDExpCipherBufSize(feed));
+ plainBlockSize = feeFEEDExpPlainBlockSize(feed);
+ numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize;
+ ctextResultLen = (numBlocks + 1) * feeFEEDExpCipherBlockSize(feed);
+ ctextResult = (unsigned char*) fmalloc(ctextResultLen);
+ ctextPtr = ctextResult;
+ ctextLenTotal = 0;
+
+ while(1) {
+ if(ptextLen <= plainBlockSize) {
+ finalBlock = 1;
+ thisPtextLen = ptextLen;
+ }
+ else {
+ finalBlock = 0;
+ thisPtextLen = plainBlockSize;
+ }
+ frtn = feeFEEDExpEncryptBlock(feed,
+ ptext,
+ thisPtextLen,
+ ctext,
+ &ctextLen,
+ finalBlock);
+ if(frtn) {
+ dbgLog(("feeFEEDExpEncrypt: encrypt error: %s\n",
+ feeReturnString(frtn)));
+ break;
+ }
+ if(ctextLen == 0) {
+ dbgLog(("feeFEEDExpEncrypt: null ciphertext\n"));
+ frtn = FR_Internal;
+ break;
+ }
+ bcopy(ctext, ctextPtr, ctextLen);
+ ctextLenTotal += ctextLen;
+ if(ctextLenTotal > ctextResultLen) {
+ dbgLog(("feeFEEDExpEncrypt: ciphertext overflow\n"));
+ frtn = FR_Internal;
+ break;
+ }
+ if(finalBlock) {
+ break;
+ }
+ ctextPtr += ctextLen;
+ ptext += thisPtextLen;
+ ptextLen -= thisPtextLen;
+ }
+
+ ffree(ctext);
+ if(frtn) {
+ ffree(ctextResult);
+ *cipherText = NULL;
+ *cipherTextLen = 0;
+ }
+ else {
+ *cipherText = ctextResult;
+ *cipherTextLen = ctextLenTotal;
+ #if FEE_DEBUG
+ if(feeFEEDExpCipherTextSize(feed, plainTextLen) !=
+ ctextLenTotal) {
+ printf("feeFEEDExpEncrypt: feeFEEDCipherTextSize "
+ "error!\n");
+ printf("ptext %d exp ctext %d actual ctext %d\n",
+ plainTextLen,
+ feeFEEDExpCipherTextSize(feed, plainTextLen),
+ ctextLenTotal);
+ }
+ #endif // FEE_DEBUG
+ }
+ return frtn;
+
+}
+
+feeReturn feeFEEDExpDecrypt(feeFEEDExp feed,
+ const unsigned char *cipherText,
+ unsigned cipherTextLen,
+ unsigned char **plainText, // malloc'd and RETURNED
+ unsigned *plainTextLen) // RETURNED
+{
+ const unsigned char *ctext;
+ unsigned ctextLen; // total to go
+ unsigned char *ptext; // per block
+ unsigned ptextLen; // per block
+ unsigned char *ptextResult; // to return
+ unsigned char *ptextPtr;
+ unsigned ptextLenTotal; // running total
+ feeReturn frtn = FR_Success;
+ int finalBlock;
+ unsigned numBlocks;
+ unsigned plainBlockSize =
+ feeFEEDExpPlainBlockSize(feed);
+ unsigned cipherBlockSize =
+ feeFEEDExpCipherBlockSize(feed);
+
+ if(cipherTextLen % cipherBlockSize) {
+ dbgLog(("feeFEEDExpDecrypt: unaligned cipherText\n"));
+ return FR_BadCipherText;
+ }
+ if(cipherTextLen == 0) {
+ dbgLog(("feeFEEDExpDecrypt: NULL cipherText\n"));
+ return FR_BadCipherText;
+ }
+
+ ptext = (unsigned char*) fmalloc(plainBlockSize);
+ ctext = cipherText;
+ ctextLen = cipherTextLen;
+ numBlocks = cipherTextLen / cipherBlockSize;
+ ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks);
+ ptextPtr = ptextResult;
+ ptextLenTotal = 0;
+
+ while(ctextLen) {
+ if(ctextLen == cipherBlockSize) {
+ finalBlock = 1;
+ }
+ else {
+ finalBlock = 0;
+ }
+ frtn = feeFEEDExpDecryptBlock(feed,
+ ctext,
+ cipherBlockSize,
+ ptext,
+ &ptextLen,
+ finalBlock);
+ if(frtn) {
+ dbgLog(("feeFEEDExpDecryptBlock: %s\n",
+ feeReturnString(frtn)));
+ break;
+ }
+ if(ptextLen == 0) {
+ /*
+ * Normal termination case for
+ * plainTextLen % plainBlockSize == 0
+ */
+ if(!finalBlock) {
+ dbgLog(("feeFEEDExpDecrypt: decrypt sync"
+ " error!\n"));
+ frtn = FR_BadCipherText;
+ }
+ break;
+ }
+ else if(ptextLen > plainBlockSize) {
+ dbgLog(("feeFEEDExpDecrypt: ptext overflow!\n"));
+ frtn = FR_Internal;
+ break;
+ }
+ else {
+ bcopy(ptext, ptextPtr, ptextLen);
+ ptextPtr += ptextLen;
+ ptextLenTotal += ptextLen;
+ }
+ ctext += cipherBlockSize;
+ ctextLen -= cipherBlockSize;
+ }
+
+ ffree(ptext);
+ if(frtn) {
+ ffree(ptextResult);
+ *plainText = NULL;
+ *plainTextLen = 0;
+ }
+ else {
+ *plainText = ptextResult;
+ *plainTextLen = ptextLenTotal;
+ }
+ return frtn;
+
+}
+
+#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */