X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_cryptkit/lib/feeFEEDExp.c diff --git a/Security/libsecurity_cryptkit/lib/feeFEEDExp.c b/Security/libsecurity_cryptkit/lib/feeFEEDExp.c deleted file mode 100644 index 4126c2bb..00000000 --- a/Security/libsecurity_cryptkit/lib/feeFEEDExp.c +++ /dev/null @@ -1,735 +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. - *************************************************************************** - * - * 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 - -#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 */