X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_cryptkit/lib/feeFEED.c diff --git a/Security/libsecurity_cryptkit/lib/feeFEED.c b/Security/libsecurity_cryptkit/lib/feeFEED.c deleted file mode 100644 index 144f7345..00000000 --- a/Security/libsecurity_cryptkit/lib/feeFEED.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* 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. - *************************************************************************** - * - * FeeFEED.c - generic, portable FEED encryption object, expanionless version - * - * 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() - * 31 Mar 1997 at Apple - * Fixed initialRS leak - * 3 Mar 1997 at Apple - * Trimmed plainBlockSize by one byte if q mod 8 = 0 - * 30 Jan 1997 at NeXT - * Created. - */ - -/* - * FIXME - a reusable init function would be nice (i.e., free up - * session-dependent state and re-init it)... - */ -#include "ckconfig.h" - -#if CRYPTKIT_ASYMMETRIC_ENABLE - -#include "feeTypes.h" -#include "feeFEED.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 "curveParams.h" -#include "feeDebug.h" -#include -#include - -#define FEED_DEBUG 0 -#define BUFFER_DEBUG 0 -#if BUFFER_DEBUG -#define bprintf(s) printf s -#else -#define bprintf(s) -#endif - -/* - * Minimum combined size of random r and s, in bytes. For small q sizes, - * r and s may be even smaller, but we never truncate them to smaller than - * this. - * This must be kept in sync with constant of same name in FEED.java. - */ -#define RS_MIN_SIZE 16 - -/* - * Private data. - */ -typedef struct { - curveParams *cp; - - /* - * the clues are initially (r * ourPriv * theirPub(+/-)). - */ - giant cluePlus; - giant clueMinus; - - /* - * sPlus and sMinus are based on the random s generated at encrypt - * time. Values are s * x1{Plus,Minus}. - */ - giant sPlus; - giant sMinus; - giant r; /* random, generated at encrypt time */ - unsigned plainBlockSize; /* plaintext block size */ - unsigned cipherBlockSize; /* ciphertext block size */ - unsigned char *initialRS; /* initial random R,S as bytes */ - unsigned initialRSSize; /* in bytes */ - feeFEEDExp feedExp; /* for encr/decr r+s params */ - - /* - * The first few blocks of ciphertext in a stream are the 2:1-FEED - * encrypted r and s parameters. While decrypting, we stash incoming - * ciphertext in rsCtext until we get enough ciphertext to decrypt - * initialRS. RsBlockCount keeps a running count of the - * cipherBlocks received. When rsBlockCount == rsSizeCipherBlocks, we - * FEEDExp-decrypt rsCtext to get r and s (actually, to get - * initialRS; r and s are extraced later in initFromRS()). - * - * During encrypt, if rsBlockCount is zero, the first thing we send as - * ciphertext is the FEED-encrypted initialRS. - */ - unsigned char *rsCtext; /* buffer for encrypted initialRS */ - unsigned rsBlockCount; /* running total of incoming rs - * cipherblocks */ - - int forEncrypt; /* added for feeFEED*TextSize() */ - - /* - * These are calculated at init time - for encrypt and - * decrypt - as an optimization. - */ - unsigned rsCtextSize; /* number of meaningful bytes in - * rsCtext */ - unsigned rsSizeCipherBlocks; /* # of our cipherblocks holding - * rsCtext */ - - /* - * temporary variables used for encrypt/decrypt. The values in these - * are 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 xm; /* ciphertext */ - giant tmp1; /* scratch */ - giant tmp2; /* scratch */ -} feedInst; - -/* - * "zero residue" indicator. - */ -#define RESID_ZERO 0xff - -/* - * cons up: - * cluePlus(0) - * clueMinus(0) - * sPlus - * sMinus - * r - * Assumes: - * cluePlus = clueMinus = ourPriv * theirPub - * initialRS - * initialRSSize - * cp - * - * Called at feeFEEDNewWithPubKey while encrypting, or upon decrypting - * first block of data. - */ -static feeReturn initFromRS(feedInst *finst) -{ - giant s; - unsigned rSize = finst->initialRSSize / 2; - - #if FEED_DEBUG - if((finst->initialRS == NULL) || - (finst->cp == NULL) || - (finst->cluePlus == NULL) || - (finst->clueMinus == NULL) || - (finst->initialRSSize == 0)) { - dbgLog(("initFromRS: resource shortage\n")); - return FR_Internal; - } - #endif // FEED_DEBUG - - finst->r = giant_with_data(finst->initialRS, rSize); - s = giant_with_data(finst->initialRS+rSize, rSize); - - #if FEED_DEBUG - if(isZero(finst->r)) { - printf("initFromRS: r = 0! initialRSSize = %d; encr = %s\n", - finst->initialRSSize, - (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); - } - if(isZero(s)) { - printf("initFromRS: s = 0! initialRSSize = %d; encr = %s\n", - finst->initialRSSize, - (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); - } - #endif // FEE_DEBUG - /* - * Justify r and s to be in [2, minimumX1Order]. - */ - lesserX1OrderJustify(finst->r, finst->cp); - lesserX1OrderJustify(s, finst->cp); - - /* - * sPlus = s * x1Plus - * sMinus = s * x1Minus - */ - finst->sPlus = newGiant(finst->cp->maxDigits); - finst->sMinus = newGiant(finst->cp->maxDigits); - gtog(finst->cp->x1Plus, finst->sPlus); - elliptic_simple(finst->sPlus, s, finst->cp); - gtog(finst->cp->x1Minus, finst->sMinus); - elliptic_simple(finst->sMinus, s, finst->cp); - - /* - * And finally, the initial clues. They are currently set to - * ourPriv * theirPub. - */ - #if FEED_DEBUG - printf("cluePlus : "); printGiant(finst->cluePlus); - printf("clueMinus: "); printGiant(finst->clueMinus); - #endif // FEED_EEBUG - - elliptic_simple(finst->cluePlus, finst->r, finst->cp); - elliptic_simple(finst->clueMinus, finst->r, finst->cp); - - #if FEED_DEBUG - printf("r : "); printGiant(finst->r); - printf("s : "); printGiant(s); - printf("sPlus : "); printGiant(finst->sPlus); - printf("sMinus : "); printGiant(finst->sMinus); - printf("cluePlus : "); printGiant(finst->cluePlus); - printf("clueMinus: "); printGiant(finst->clueMinus); - #endif // FEED_DEBUG - - freeGiant(s); - return FR_Success; -} - -/* - * Alloc and init a feeFEED object associated with specified public and - * private keys. - */ -feeFEED feeFEEDNewWithPubKey(feePubKey myPrivKey, - feePubKey theirPubKey, - int forEncrypt, // 0 ==> decrypt 1 ==> encrypt - feeRandFcn randFcn, // optional - void *randRef) -{ - feedInst *finst; - giant privGiant; - key k; - unsigned expPlainSize; - unsigned expCipherSize; - unsigned expBlocks; - - if(!curveParamsEquivalent(feePubKeyCurveParams(theirPubKey), - feePubKeyCurveParams(myPrivKey))) { - dbgLog(("feeFEEDNewWithPubKey: Incompatible Keys\n")); - return NULL; - } - finst = (feedInst*) fmalloc(sizeof(feedInst)); - bzero(finst, sizeof(feedInst)); - finst->forEncrypt = forEncrypt; - finst->cp = curveParamsCopy(feePubKeyCurveParams(theirPubKey)); - finst->rsBlockCount = 0; - finst->xp = newGiant(finst->cp->maxDigits); - finst->xm = newGiant(finst->cp->maxDigits); - finst->tmp1 = newGiant(finst->cp->maxDigits); - if(forEncrypt) { - finst->tmp2 = newGiant(finst->cp->maxDigits); - } - - /* - * cluePlus = ourPriv * theirPub+ - * clueMinus = ourPriv * theirPub- - */ - finst->cluePlus = newGiant(finst->cp->maxDigits); - finst->clueMinus = newGiant(finst->cp->maxDigits); - privGiant = feePubKeyPrivData(myPrivKey); - if(privGiant == NULL) { - dbgLog(("feeFEEDNewWithPubKey: no private key\n")); - goto abort; - } - k = feePubKeyPlusCurve(theirPubKey); - gtog(k->x, finst->cluePlus); // cluePlus = theirPub+ - elliptic_simple(finst->cluePlus, privGiant, finst->cp); - k = feePubKeyMinusCurve(theirPubKey); - gtog(k->x, finst->clueMinus); // theirPub- - elliptic_simple(finst->clueMinus, privGiant, finst->cp); - - /* - * Set up block sizes. - */ - if(finst->cp->primeType == FPT_General) { - unsigned blen = bitlen(finst->cp->basePrime); - - finst->plainBlockSize = blen / 8; - if((blen & 0x7) == 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--; - } - } - finst->cipherBlockSize = finst->cp->minBytes + 1; - - /* - * the size of initialRS is subject to tweaking - if we make it - * not a multiple of plainBlockSize, we save one FEEDExp cipherBlock - * in our ciphertext. - */ - finst->initialRSSize = finst->plainBlockSize * 2; - if(finst->initialRSSize > RS_MIN_SIZE) { - unsigned minPlainBlocks; - unsigned maxSize; - - /* - * How many plainblocks to hold RS_MIN_SIZE? - */ - minPlainBlocks = (RS_MIN_SIZE + finst->plainBlockSize - 1) / - finst->plainBlockSize; - - /* - * Max size = that many plainblocks, less 2 bytes (to avoid - * extra residue block). - */ - maxSize = minPlainBlocks * finst->plainBlockSize - 2; - - /* - * But don't bother with more than 2 plainblocks worth - */ - if(finst->initialRSSize > maxSize) { - finst->initialRSSize = maxSize; - } - } - /* else leave it alone, that's small enough */ - - if(forEncrypt) { - feeRand frand = NULL; - - /* - * Encrypt-capable FEEDExp object - */ - finst->feedExp = feeFEEDExpNewWithPubKey(theirPubKey, - randFcn, - randRef); - if(finst->feedExp == NULL) { - goto abort; - } - - /* - * Generate initial r and s data. - */ - finst->initialRS = (unsigned char*) fmalloc(finst->initialRSSize); - if(randFcn != NULL) { - randFcn(randRef, finst->initialRS, finst->initialRSSize); - } - else { - frand = feeRandAlloc(); - feeRandBytes(frand, finst->initialRS, finst->initialRSSize); - feeRandFree(frand); - } - if(initFromRS(finst)) { - goto abort; - } - } - else { - /* - * Decrypt-capable FEEDExp object - */ - finst->feedExp = feeFEEDExpNewWithPubKey(myPrivKey, - randFcn, - randRef); - if(finst->feedExp == NULL) { - goto abort; - } - - } - - /* - * Figure out how many of our cipherblocks it takes to hold - * a FEEDExp-encrypted initialRS. If initialRSSize is an exact - * multiple of expPlainSize, we get an additional feedExp - * residue block. - */ - expPlainSize = feeFEEDExpPlainBlockSize(finst->feedExp); - expCipherSize = feeFEEDExpCipherBlockSize(finst->feedExp); - expBlocks = (finst->initialRSSize + expPlainSize - 1) / - expPlainSize; - if((finst->initialRSSize % expPlainSize) == 0) { - expBlocks++; - } - - /* - * Total meaningful bytes of encrypted initialRS - */ - finst->rsCtextSize = expBlocks * expCipherSize; - - /* - * Number of our cipherblocks it takes to hold rsCtextSize - */ - finst->rsSizeCipherBlocks = (finst->rsCtextSize + - finst->cipherBlockSize - 1) / finst->cipherBlockSize; - if(!forEncrypt) { - finst->rsCtext = (unsigned char*) fmalloc(finst->rsSizeCipherBlocks * - finst->cipherBlockSize); - } - - /* - * Sanity check... - */ - #if FEED_DEBUG - { - unsigned fexpBlockSize = feeFEEDExpCipherBlockSize(finst->feedExp); - - /* - * FEEDExp has one more giant in ciphertext, plaintext is - * same size - */ - if((finst->cipherBlockSize + finst->cp->minBytes) != - fexpBlockSize) { - dbgLog(("feeFEEDNewWithPubKey: FEEDExp CBlock Size " - "screwup\n")); - goto abort; - } - fexpBlockSize = feeFEEDExpPlainBlockSize(finst->feedExp); - if(fexpBlockSize != finst->plainBlockSize) { - dbgLog(("feeFEEDNewWithPubKey: FEEDExp PBlock Size " - "screwup\n")); - goto abort; - } - } - #endif // FEED_DEBUG - - return finst; - -abort: - feeFEEDFree(finst); - return NULL; -} - -void feeFEEDFree(feeFEED feed) -{ - feedInst *finst = (feedInst*) feed; - - if(finst->cp) { - freeCurveParams(finst->cp); - } - if(finst->initialRS) { - ffree(finst->initialRS); - } - if(finst->cluePlus) { - freeGiant(finst->cluePlus); - } - if(finst->clueMinus) { - freeGiant(finst->clueMinus); - } - if(finst->sPlus) { - freeGiant(finst->sPlus); - } - if(finst->sMinus) { - freeGiant(finst->sMinus); - } - if(finst->r) { - freeGiant(finst->r); - } - if(finst->feedExp) { - feeFEEDExpFree(finst->feedExp); - } - if(finst->rsCtext) { - ffree(finst->rsCtext); - } - if(finst->xp) { - freeGiant(finst->xp); - } - if(finst->xm) { - freeGiant(finst->xm); - } - if(finst->tmp1) { - freeGiant(finst->tmp1); - } - if(finst->tmp2) { - freeGiant(finst->tmp2); - } - ffree(finst); -} - -unsigned feeFEEDPlainBlockSize(feeFEED feed) -{ - feedInst *finst = (feedInst *) feed; - - return finst->plainBlockSize; -} - -unsigned feeFEEDCipherBlockSize(feeFEED feed) -{ - feedInst *finst = (feedInst *) feed; - - return finst->cipherBlockSize; -} - -/* - * Calculate size of buffer currently needed to encrypt one block of - * plaintext. Also used to calculate required input during decrypt - * to get any output. - */ -unsigned feeFEEDCipherBufSize(feeFEED feed, - int finalBlock) -{ - feedInst *finst = (feedInst *) feed; - unsigned blocks = 1; // always at least one block of ciphertext - - if(finst->rsBlockCount == 0) { - /* haven't sent/seen encrypted RS yet */ - blocks += finst->rsSizeCipherBlocks; - } - - if(finalBlock) { - /* only needed if ptext is aligned, but tell caller to malloc */ - blocks++; - } - bprintf(("$$$ feeFEEDCipherBufSize( %s, %s): rtn 0x%x\n", - finst->forEncrypt ? "encrypt" : "decrypt", - finalBlock ? " final" : "!final", - blocks * finst->cipherBlockSize)); - return blocks * finst->cipherBlockSize; -} - -/* - * Return the size of ciphertext currently needed to encrypt specified - * size of plaintext. Also can be used to calculate size of ciphertext - * which can be decrypted into specified size of plaintext. - */ -unsigned feeFEEDCipherTextSize(feeFEED feed, - unsigned plainTextSize, - int finalBlock) -{ - feedInst *finst = (feedInst *) feed; - - /* how many blocks of plaintext? */ - unsigned blocks = (plainTextSize + finst->plainBlockSize - 1) / - finst->plainBlockSize; - - if(finst->forEncrypt) { - /* have we generated RS? */ - if(finst->rsBlockCount == 0) { - /* haven't sent encrypted RS yet */ - blocks += finst->rsSizeCipherBlocks; - } - - /* final? residue? */ - if(finalBlock) { - if((plainTextSize % finst->plainBlockSize) == 0) { - blocks++; - } - } - } /* encrypting */ - else { - /* - * Decrypting - how much ciphertext can we decrypt safely into - * specified plaintext? Add in RS if we haven't seen it all - * yet. - */ - #if BUFFER_DEBUG - if(finst->rsBlockCount > finst->rsSizeCipherBlocks) { - printf("******HEY! rsBlockCount overflow! (blockCount %d rsSize %d)\n", - finst->rsBlockCount, finst->rsSizeCipherBlocks); - } - #endif - blocks += (finst->rsSizeCipherBlocks - finst->rsBlockCount); - } - bprintf(("$$$ feeFEEDCipherTextSize(%s, %s, 0x%x): rtn 0x%x\n", - finst->forEncrypt ? "encrypt" : "decrypt", - finalBlock ? " final" : "!final", - plainTextSize, blocks * finst->cipherBlockSize)); - return blocks * finst->cipherBlockSize; -} - -/* - * Return the size of plaintext currently needed to decrypt specified size - * of ciphertext. Also can be used to calculate size of plaintext - * which can be encrypted into specified size of ciphertext. - */ -unsigned feeFEEDPlainTextSize(feeFEED feed, - unsigned cipherTextSize, - int finalBlock) // ignored if !forEncrypt -{ - feedInst *finst = (feedInst *) feed; - - /* start with basic cipher block count */ - unsigned cipherBlocks = (cipherTextSize + finst->cipherBlockSize - 1) / - finst->cipherBlockSize; - - /* where are we in the RS stream? */ - unsigned rsBlocksToGo = finst->rsSizeCipherBlocks - finst->rsBlockCount; - if(finst->forEncrypt) { - /* - * Encrypting, seeking plaintext size we can encrypt given - * a specified size of ciphertext. - */ - if(rsBlocksToGo >= cipherBlocks) { - /* no room! next encrypt would overflow ctext buffer! */ - return 0; - } - cipherBlocks -= rsBlocksToGo; - - /* another constraint - residue */ - if(finalBlock) { - if(cipherBlocks) { - /* skip if already zero... */ - cipherBlocks--; - } - } - } /* encrypting */ - else { - /* decrypting */ - if(rsBlocksToGo >= cipherBlocks) { - /* still processing RS, no plaintext will be generated. Play it real - * safe and just tell caller one block. */ - cipherBlocks = 1; - } - else { - /* diminish by size of RS to be gobbled with no output */ - cipherBlocks -= rsBlocksToGo; - } - } - bprintf(("$$$ feeFEEDPlainTextSize( %s, %s, 0x%x): rtn 0x%x\n", - finst->forEncrypt ? "encrypt" : "decrypt", - finalBlock ? " final" : "!final", - cipherTextSize, cipherBlocks * finst->plainBlockSize)); - return cipherBlocks * finst->plainBlockSize; -} - -/* - * Bits in last byte of cipherblock - */ -#define CLUE_BIT 0x01 /* 1 ==> plus curve */ -#define CLUE_PLUS 0x01 -#define CLUE_MINUS 0x00 -#define PARITY_BIT 0x02 /* 1 ==> plus 's' arg to elliptic_add() */ -#define PARITY_PLUS 0x02 -#define PARITY_MINUS 0x00 - -/* - * Encrypt a block or less of data. Caller malloc's cipherText. - * Generates up to feeFEEDCipherBufSize() bytes of ciphertext. - */ -feeReturn feeFEEDEncryptBlock(feeFEED feed, - const unsigned char *plainText, - unsigned plainTextLen, - unsigned char *cipherText, - unsigned *cipherTextLen, // RETURNED - int finalBlock) -{ - feedInst *finst = (feedInst *) feed; - unsigned ctextLen = 0; - feeReturn frtn = FR_Success; - int whichCurve; - giant thisClue; // not alloc'd or freed - giant thisS; // ditto - unsigned char clueByte; - - if(plainTextLen > finst->plainBlockSize) { - return FR_IllegalArg; - } - if((plainTextLen < finst->plainBlockSize) && !finalBlock) { - return FR_IllegalArg; - } - if(finst->initialRS == NULL) { - /* - * Init'd for decrypt? - */ - return FR_IllegalArg; - } - - /* - * First block - encrypt initialRS via FEEDExp - */ - if(finst->rsBlockCount == 0) { - unsigned char *thisCtext; // malloc's by FEEDExp - unsigned padLen; - - if(finst->initialRS == NULL) { - /* - * init'd for decrypt or reused - */ - dbgLog(("feeFEEDEncryptBlock: NULL initialRS!\n")); - return FR_IllegalArg; - } - - frtn = feeFEEDExpEncrypt(finst->feedExp, - finst->initialRS, - finst->initialRSSize, - &thisCtext, - &ctextLen); - if(frtn) { - /* - * Should never happen... - */ - dbgLog(("feeFEEDEncryptBlock: error writing encrypted" - " initialRS (%s)\n", feeReturnString(frtn))); - return FR_Internal; - } - bcopy(thisCtext, cipherText, ctextLen); - cipherText += ctextLen; - ffree(thisCtext); - - finst->rsBlockCount = finst->rsSizeCipherBlocks; - padLen = finst->cipherBlockSize - - (ctextLen % finst->cipherBlockSize); // zeros to write - - #if 0 /* FEED_DEBUG */ - - /* - * Hard-coded assumptions and tests about initRSSize... - * Currently we assume that initRSSize % expBlockSize = 0 - */ - if((ctextLen / finst->cipherBlockSize) != 5) { - dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (1)\n")); - return FR_Internal; - } - if(padLen != 3) { - dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (2)\n")); - return FR_Internal; - } - #endif // FEED_DEBUG - - /* - * pad to multiple of (our) cipherblock size. - */ - while(padLen) { - *cipherText++ = 0; - ctextLen++; - padLen--; - } - } - - /* - * plaintext to giant xp - */ - if(finalBlock) { - unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize); - bzero(ptext, finst->plainBlockSize); - if(plainTextLen) { - /* - * skip for empty block with resid length 0 - */ - bcopy(plainText, ptext, plainTextLen); - } - if(plainTextLen < finst->plainBlockSize) { - if(plainTextLen == 0) { - /* - * Special case - resid block with no actual plaintext. - * Can't actually write zero here; it screws up - * deserializing the giant during decrypt - */ - ptext[finst->plainBlockSize - 1] = RESID_ZERO; - bprintf(("=== FEED encrypt: RESID_ZERO\n")); - } - else { - ptext[finst->plainBlockSize - 1] = plainTextLen; - bprintf(("=== FEED encrypt: resid len 0x%x\n", plainTextLen)); - } - } - /* - * else handle evenly aligned case (i.e., finalBlock true - * and (plainTextLen == plainBlockSize)) below... - */ - deserializeGiant(ptext, finst->xp, finst->plainBlockSize); - ffree(ptext); - } - else { - deserializeGiant(plainText, finst->xp, plainTextLen); - } - - /* - * encrypt xp - * xm = xp + clue(+/-) - * determine parity needed to restore xp - * parity = ((xm + clue(+/-) == xp) ? 1 : -1 - * and adjust clue - * clue[n+1] = r * clue[n] + (s * P1) - */ - whichCurve = which_curve(finst->xp, finst->cp); - if(whichCurve == CURVE_PLUS) { - thisClue = finst->cluePlus; - thisS = finst->sPlus; - clueByte = CLUE_PLUS; - } - else { - thisClue = finst->clueMinus; - thisS = finst->sMinus; - clueByte = CLUE_MINUS; - } - // calculate xm - elliptic_add(thisClue, finst->xp, finst->xm, finst->cp, SIGN_PLUS); - // save xm + clue in tmp1 - elliptic_add(finst->xm, thisClue, finst->tmp1, finst->cp, SIGN_PLUS); - // Adjust clue - elliptic_simple(thisClue, finst->r, finst->cp); - gtog(thisClue, finst->tmp2); - elliptic_add(finst->tmp2, thisS, thisClue, finst->cp, SIGN_PLUS); - - /* - * Calculate parity - */ - if(gcompg(finst->tmp1, finst->xp) == 0) { - clueByte |= PARITY_PLUS; - } - - /* - * Ciphertext = (xm, clueByte) - */ - serializeGiant(finst->xm, cipherText, finst->cp->minBytes); - cipherText += finst->cp->minBytes; - ctextLen += finst->cp->minBytes; - *cipherText++ = clueByte; - ctextLen++; - - #if FEED_DEBUG - printf("encrypt clue %d\n", clueByte); - printf(" xp : "); printGiant(finst->xp); - printf(" xm : "); printGiant(finst->xm); - printf(" cluePlus :"); printGiant(finst->cluePlus); - printf(" clueMinus :"); printGiant(finst->clueMinus); - #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 - - frtn = feeFEEDEncryptBlock(feed, - NULL, // plainText not used - 0, // resid - cipherText, // append... - &moreCipher, - 1); - if(frtn == FR_Success) { - ctextLen += moreCipher; - } - } - bprintf(("=== FEED encryptBlock ptextLen 0x%x ctextLen 0x%x\n", - plainTextLen, ctextLen)); - - *cipherTextLen = ctextLen; - return frtn; -} - -/* - * Decrypt (exactly) a block of data. Caller malloc's plainText. Always - * generates feeFEEDPlainBlockSize of plaintext, unless finalBlock is - * non-zero (in which case feeFEEDPlainBlockSize or less bytes of plainText are - * generated). - */ -feeReturn feeFEEDDecryptBlock(feeFEED feed, - const unsigned char *cipherText, - unsigned cipherTextLen, - unsigned char *plainText, - unsigned *plainTextLen, // RETURNED - int finalBlock) -{ - feedInst *finst = (feedInst *) feed; - feeReturn frtn = FR_Success; - unsigned char clueByte; - giant thisClue; // not alloc'd - giant thisS; // ditto - int parity; - - if(finst->rsCtext == NULL) { - /* - * Init'd for encrypt? - */ - return FR_IllegalArg; - } - if(cipherTextLen != finst->cipherBlockSize) { - dbgLog(("feeFEEDDecryptBlock: bad cipherTextLen\n")); - return FR_IllegalArg; - } - if(finst->rsBlockCount < finst->rsSizeCipherBlocks) { - /* - * Processing initialRS, FEEDExp-encrypted - */ - unsigned char *rsPtr = finst->rsCtext + - (finst->rsBlockCount * finst->cipherBlockSize); - unsigned feedExpCipherSize; - - if(finalBlock) { - dbgLog(("feeFEEDDecryptBlock: incomplete initialRS\n")); - return FR_BadCipherText; - } - bcopy(cipherText, rsPtr, finst->cipherBlockSize); - finst->rsBlockCount++; - if(finst->rsBlockCount < finst->rsSizeCipherBlocks) { - /* - * Not done with this yet... - */ - bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (1)\n", - cipherTextLen)); - *plainTextLen = 0; - return FR_Success; - } - - #if FEED_DEBUG - if((finst->rsBlockCount * finst->cipherBlockSize) < - finst->rsCtextSize) { - dbgLog(("feeFEEDDecryptBlock: rsCtextSize underflow!\n")); - return FR_Internal; - } - #endif // FEED_DEBUG - - /* - * OK, we should have the FEEDExp ciphertext for initialRS - * in rsCtext. Note the last few bytes are extra; we don't - * pass them to FEEDExp. - */ - feedExpCipherSize = feeFEEDCipherBlockSize(finst->feedExp); - frtn = feeFEEDExpDecrypt(finst->feedExp, - finst->rsCtext, - finst->rsCtextSize, - &finst->initialRS, - &finst->initialRSSize); - if(frtn) { - dbgLog(("feeFEEDDecryptBlock: error decrypting " - "initialRS (%s)\n", feeReturnString(frtn))); - return FR_BadCipherText; - } - - /* - * we already know how long this should be... - */ - if(finst->initialRSSize != finst->initialRSSize) { - dbgLog(("feeFEEDDecryptBlock: initialRS sync error\n")); - return FR_BadCipherText; - } - - /* - * Set up clues - */ - if(initFromRS(finst)) { - dbgLog(("feeFEEDDecryptBlock: bad initialRS\n")); - return FR_BadCipherText; - } - else { - /* - * Normal completion of last cipherblock containing - * initialRS. - */ - bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (2)\n", - cipherTextLen)); - *plainTextLen = 0; - return FR_Success; - } - } - - /* - * grab xm and clueByte from cipherText - */ - deserializeGiant(cipherText, finst->xm, finst->cp->minBytes); - cipherText += finst->cp->minBytes; - clueByte = *cipherText; - - if((clueByte & CLUE_BIT) == CLUE_PLUS) { - thisClue = finst->cluePlus; - thisS = finst->sPlus; - } - else { - thisClue = finst->clueMinus; - thisS = finst->sMinus; - } - if((clueByte & PARITY_BIT) == PARITY_PLUS) { - parity = SIGN_PLUS; - } - else { - parity = SIGN_MINUS; - } - - /* - * recover xp - * xp = xm + clue(+/-) w/parity - * adjust clue - * clue[n+1] = r * clue[n] + (s * P1) - */ - elliptic_add(thisClue, finst->xm, finst->xp, finst->cp, parity); - - elliptic_simple(thisClue, finst->r, finst->cp); - gtog(thisClue, finst->tmp1); - elliptic_add(finst->tmp1, thisS, thisClue, finst->cp, SIGN_PLUS); - - /* - * plaintext in xp - */ - #if FEED_DEBUG - printf("decrypt clue %d\n", clueByte); - printf(" xp : "); printGiant(finst->xp); - printf(" xm : "); printGiant(finst->xm); - printf(" cluePlus :"); printGiant(finst->cluePlus); - printf(" clueMinus :"); printGiant(finst->clueMinus); - #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(*plainTextLen == RESID_ZERO) { - bprintf(("=== FEED Decrypt: RESID_ZERO\n")); - *plainTextLen = 0; - } - else if(*plainTextLen > (finst->plainBlockSize - 1)) { - dbgLog(("feeFEEDDecryptBlock: ptext overflow!\n")); - bprintf(("feeFEEDDecryptBlock: ptext overflow!\n")); - frtn = FR_BadCipherText; - } - else { - bprintf(("=== FEED Decrypt: resid len 0x%x\n", *plainTextLen)); - bcopy(ptext, plainText, *plainTextLen); - } - ffree(ptext); - } - else { - *plainTextLen = finst->plainBlockSize; - serializeGiant(finst->xp, plainText, *plainTextLen); - } - bprintf(("=== FEED decryptBlock ptextLen 0x%x ctextLen 0x%x\n", - *plainTextLen, cipherTextLen)); - - return frtn; -} - -/* - * Convenience routines to encrypt & decrypt multi-block data. - */ -feeReturn feeFEEDEncrypt(feeFEED 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; // size of ctextResult - unsigned char *ctextPtr; - unsigned ctextLenTotal; // running total - feeReturn frtn; - int finalBlock; - unsigned numBlocks; - unsigned plainBlockSize; - #if FEE_DEBUG - unsigned expectedCtextSize; - - expectedCtextSize = feeFEEDCipherTextSize(feed, plainTextLen, 1); - #endif - - if(plainTextLen == 0) { - dbgLog(("feeFEEDDecrypt: NULL plainText\n")); - return FR_IllegalArg; - } - - ptext = plainText; - ptextLen = plainTextLen; - ctext = (unsigned char*) fmalloc(feeFEEDCipherBufSize(feed, 1)); - plainBlockSize = feeFEEDPlainBlockSize(feed); - numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize; - - /* - * Calculate the worst-case size needed to hold all of the ciphertext - */ - ctextResultLen = feeFEEDCipherTextSize(feed, plainTextLen, 1); - ctextResult = (unsigned char*) fmalloc(ctextResultLen); - ctextPtr = ctextResult; - ctextLenTotal = 0; - - while(1) { - if(ptextLen <= plainBlockSize) { - finalBlock = 1; - thisPtextLen = ptextLen; - } - else { - finalBlock = 0; - thisPtextLen = plainBlockSize; - } - frtn = feeFEEDEncryptBlock(feed, - ptext, - thisPtextLen, - ctext, - &ctextLen, - finalBlock); - if(frtn) { - dbgLog(("feeFEEDEncrypt: encrypt error: %s\n", - feeReturnString(frtn))); - break; - } - if(ctextLen == 0) { - dbgLog(("feeFEEDEncrypt: null ciphertext\n")); - frtn = FR_Internal; - break; - } - bcopy(ctext, ctextPtr, ctextLen); - ctextLenTotal += ctextLen; - if(ctextLenTotal > ctextResultLen) { - dbgLog(("feeFEEDEncrypt: 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(expectedCtextSize != ctextLenTotal) { - printf("feeFEEDEncrypt: feeFEEDCipherTextSize error!\n"); - printf("ptext %d exp ctext %d actual ctext %d\n", - plainTextLen, - expectedCtextSize, - ctextLenTotal); - } - #endif // FEE_DEBUG - } - return frtn; - -} - -feeReturn feeFEEDDecrypt(feeFEED 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 = feeFEEDPlainBlockSize(feed); - unsigned cipherBlockSize = feeFEEDCipherBlockSize(feed); - - if(cipherTextLen % cipherBlockSize) { - dbgLog(("feeFEEDDecrypt: unaligned cipherText\n")); - return FR_BadCipherText; - } - if(cipherTextLen == 0) { - dbgLog(("feeFEEDDecrypt: 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 = feeFEEDDecryptBlock(feed, - ctext, - cipherBlockSize, - ptext, - &ptextLen, - finalBlock); - if(frtn) { - dbgLog(("feeFEEDDecryptBlock: %s\n", - feeReturnString(frtn))); - break; - } - if(ptextLen) { - if(ptextLen > plainBlockSize) { - dbgLog(("feeFEEDDecrypt: ptext overflow!\n")); - frtn = FR_Internal; - break; - } - bcopy(ptext, ptextPtr, ptextLen); - ptextPtr += ptextLen; - ptextLenTotal += ptextLen; - } - /* - * note ptextLen == 0 is normal termination case for - * plainTextLen % plainBlockSize == 0. - * Also expected for first 4 blocks of ciphertext; - * proceed (we break when ctextLen is exhausted). - */ - 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 */