X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_comcryption/lib/comcryptPriv.c?ds=sidebyside diff --git a/Security/libsecurity_comcryption/lib/comcryptPriv.c b/Security/libsecurity_comcryption/lib/comcryptPriv.c new file mode 100644 index 00000000..873b32c8 --- /dev/null +++ b/Security/libsecurity_comcryption/lib/comcryptPriv.c @@ -0,0 +1,540 @@ +/* + * Copyright (c) 1997,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "comcryptPriv.h" +#include +#include +#include +#ifdef macintosh +#include +#endif + +/* if NULL, use our own */ +comMallocExternFcn *comMallocExt = NULL; +comFreeExternFcn *comFreeExt = NULL; + +#if COM_STATS +comStats _comStats; + +void resetComStats() +{ + memset(&_comStats, 0, sizeof(comStats)); +} + +void getComStats(comStats *stats) +{ + *stats = _comStats; +} + +#else /*COM_STATS*/ + +#define incrComStat(stat, num) + +#endif /*COM_STATS*/ + +/* + * Generate a symbol permutation from the key. + */ +void key_perm( + const unsigned char *key, + int keybytes, + unsigned char *map, + unsigned char *invmap) +{ + int i, j, tmp, sum; + + for(sum = 0, j = 0; j < keybytes; j++) { + sum += key[j]; + } + for(j=0; j < 256; j++) { + map[j] = j; + } + for(j=0; j < 255; j++) { + i = (key[j % keybytes] + j*sum) & 0xff; + tmp = map[i]; + map[i] = map[j]; + map[j] = tmp; + } + for(j=0; j<256; j++) { + invmap[map[j]] = j; + } +} + +int keybyte( + const unsigned char *key, + int keybytes, + int index) +{ + return((int) key[index % keybytes]); +} + +int keynybble( + const unsigned char *key, + int keybytes, + int index) +{ + int i = index % (2*keybytes); + int j; + + j = key[i>>1]; /* Which byte. */ + if(i & 1) j >>= 4; /* Which nybble. */ + return(j & 0xf); +} + +/* + * Hash a key array. + */ + +#define HASH_SEED 3 +#define HASH_REDUCE 1023 + +static unsigned keyHash(const unsigned char *key, unsigned keylen) +{ + unsigned x = HASH_SEED; /* Any seed in [1,p-1]. Like SEED = 3. */ + unsigned ctr; + + for(ctr=0; ctrcodeBufSize = comcryptMaxOutBufSize(NULL, + CC_BLOCK_SIZE, + CCOP_COMCRYPT, + 1); + cbuf->codeBuf = (unsigned char *)ascMalloc(cbuf->codeBufSize); + + /* + * max size needed for level2Buf is the MaxOutBufSize of comcrypting + * a whole block of byte code. Note we assume that MaxOutBufSize(n) >= n. + */ + cbuf->level2BufSize = comcryptMaxOutBufSize(NULL, + MAX_TOKENS, // one byte per token + CCOP_COMCRYPT, + 1); + cbuf->level2Buf = (unsigned char *)ascMalloc(cbuf->level2BufSize); + + cbuf->queue = (queueElt *)ascMalloc(sizeof(queueElt) * QLEN); + + #if QUEUE_LOOKAHEAD + /* + * Might want to do this dynamically, though that requires the malloc + * of the lookAhead buffer to be done in initCodeBufs(), not here (at + * comcryptAlloc() time). + * + * FIXME : should do the malloc of lookAhead buffer lazily for + * non-Mac platforms. + */ + cbuf->lookAhead = (unsigned char *)ascMalloc(LOOKAHEAD_SIZE); + #else /* QUEUE_LOOKAHEAD */ + cbuf->lookAhead = NULL; + #endif /* QUEUE_LOOKAHEAD */ + + /* + * This maybe should also be done dynamically, lazily... + */ + cbuf->sigArray = (unsigned *)ascMalloc((MAX_TOKENS + 1) * sizeof(unsigned)); +} + +void initCodeBufs( + comcryptBuf *cbuf, + const unsigned char *key, + unsigned keyLen, + unsigned char laEnable, + unsigned char sigSeqEnable) +{ + unsigned ct; + unsigned qval; + unsigned char khash = (unsigned char)keyHash(key, keyLen); + + cbuf->nybbleDex = khash; + + if(laEnable) { + memset(cbuf->lookAhead, 0, LOOKAHEAD_SIZE); + } + + laprintf(("initing queue and lookahead\n")); + + for(ct=0; ctqueue[ct] = qval; + if(laEnable) { + markInQueue(cbuf, qval, 1); + } + } + // note cbuf->nybbleDex = khash on return... + + cbuf->f1 = F1_DEFAULT; + cbuf->f2 = F2_DEFAULT; + cbuf->jmatchThresh = THRESH_2LEVEL_JMATCH_DEF; + cbuf->minByteCode = THRESH_2LEVEL_NUMBYTECODES_DEF; + if(sigSeqEnable) { + initSigSequence(cbuf, key, keyLen); + } +} + +void freeCodeBufs(comcryptBuf *cbuf) +{ + if(cbuf->queue != NULL) { + ascFree(cbuf->queue); + } + if(cbuf->codeBuf != NULL) { + ascFree(cbuf->codeBuf); + } + if(cbuf->level2Buf != NULL) { + ascFree(cbuf->level2Buf); + } + if(cbuf->nextBuf != NULL) { + freeCodeBufs(cbuf->nextBuf); + ascFree(cbuf->nextBuf); + cbuf->nextBuf = NULL; + } + if(cbuf->lookAhead != NULL) { + ascFree(cbuf->lookAhead); + } + if(cbuf->sigArray != NULL) { + ascFree(cbuf->sigArray); + } +} + +void serializeInt( + unsigned i, + unsigned char *buf) +{ + buf[0] = (unsigned char)(i >> 24); + buf[1] = (unsigned char)(i >> 16); + buf[2] = (unsigned char)(i >> 8); + buf[3] = (unsigned char)(i & 0xff); +} + +unsigned deserializeInt(unsigned char *buf) +{ + unsigned i; + + i = ((unsigned)buf[0]) << 24; + i |= ((unsigned)buf[1]) << 16; + i |= ((unsigned)buf[2]) << 8; + i |= buf[3]; + return i; +} + +#if COM_PARAM_ENABLE + +unsigned getF1(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.f1; +} + +void setF1(comcryptObj cobj, unsigned f1) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.f1 = f1; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->f1 = f1; + } +} + +unsigned getF2(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.f2; +} + +void setF2(comcryptObj cobj, unsigned f2) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.f2 = f2; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->f2 = f2; + } +} + +unsigned getJmatchThresh(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.jmatchThresh; +} + +void setJmatchThresh(comcryptObj cobj, unsigned jmatchThresh) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.jmatchThresh = jmatchThresh; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->jmatchThresh = jmatchThresh; + } +} + +unsigned getMinByteCode(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.minByteCode; +} + +void setMinByteCode(comcryptObj cobj, unsigned minByteCode) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.minByteCode = minByteCode; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->minByteCode = minByteCode; + } +} + +#endif /*COM_PARAM_ENABLE*/ + + +#if COM_LA_DEBUG + +/* + * Verify integrity of lookahead w.r.t. queue. + */ +int testLookAhead(comcryptBuf *cbuf, int i1, int i2) +{ + unsigned i; + + if(!cbuf->laEnable) { + return 0; + } + for(i=0; iqueue[i])) { + printf("aaagh, corrupted lookahead - in queue[], !inQueue()\n"); + printf("i=0x%x i1=0x%x i2=0x%x\n", + i, i1, i2); + printf("\n"); + exit(1); + } + } + //return initTestLookAhead(cbuf); + return 0; +} + +int initTestLookAhead(comcryptBuf *cbuf) +{ + #if QUEUE_LOOKAHEAD_BIT + + unsigned codeWord = 0; + unsigned char bit; + unsigned short byte; + unsigned char *la = cbuf->lookAhead; + + for(byte=0; bytequeue[i] == codeWord) { + found = 1; + break; + } + } + if(!found) { + printf("***corrupted init lookahead - in l.a., " + "not in queue[]\n"); + printf("codeWord 0x%x\n", codeWord); + printf("\n"); + exit(1); + } + } + codeWord++; + } + } + + #endif /* QUEUE_LOOKAHEAD_BIT */ + return 0; +} + +#endif /* COM_LA_DEBUG */ + +void initSigSequence(comcryptBuf *cbuf, + const unsigned char *key, + unsigned keyLen) +{ + unsigned seed = IN_OFFSET; + unsigned j; + + for(j=0; jsigArray[0] = (unsigned short)seed; +} + +#if 0 +/* + * Called once per token bit, after processing the token. + */ +void nextSigWord(comcryptBuf *cbuf, + unsigned sigDex, // same as tokenDex + unsigned match, + unsigned above) // jabove, keyabove +{ + unsigned offset; + unsigned short *sigArray = cbuf->sigArray; + + #if COM_DEBUG + if(sigDex == 0) { + printf("nextSigWord underflow\n"); + exit(1); + } + if(sigDex > MAX_TOKENS) { + printf("nextSigWord overflow\n"); + exit(1); + } + #endif + + if(match) { + offset = IN_OFFSET; + } + else { + offset = OUT_OFFSET; + } +#if 1 + sigArray[sigDex] = (sigArray[sigDex-1] * (above + offset)) % HASH_PRIME; +#endif +} +#endif + +/* + * Obfuscate a block of ciphertext. + */ +void sigMunge(comcryptBuf *cbuf, + const unsigned char *tokenPtr, + unsigned numTokens, + unsigned char *byteCodePtr, + unsigned char *longCodePtr) +{ + unsigned char tokenBit = 0x01; + unsigned token; + unsigned short sig; + + for(token=0; tokensigArray[token]; + if(*tokenPtr & tokenBit) { + /* no match - munge longCode - written MSB first */ + *longCodePtr++ ^= (unsigned char)(sig >> 8); + *longCodePtr++ ^= (unsigned char)sig; + } + else { + /* match - munge byteCode */ + *byteCodePtr++ ^= (unsigned char)sig; + } + tokenBit <<= 1; + if(tokenBit == 0) { + tokenBit = 0x01; + tokenPtr++; + } + } +} + + +/* + * All this can be optimized and tailored to specific platforms, of course... + */ + +void *ascMalloc(unsigned size) +{ + #ifdef macintosh + + Handle h; + OSErr err; + Ptr p; + + #endif /* mac */ + + if(comMallocExt != NULL) { + return (comMallocExt)(size); + } + + #ifdef macintosh + + h = nil; + err = errSecSuccess; + + h = NewHandleSys(size); // system heap is not paged + do{ + HLockHi(h); // will move low in system heap + err = MemError(); + if( err != errSecSuccess ) break; + p = *h; + }while(0); + if( err != errSecSuccess ){ + return NULL; + } + return p; + + #else /* others...*/ + return malloc(size); + #endif +} + +void ascFree(void *data) +{ + #ifdef macintosh + Handle h; + #endif + + if(comFreeExt != NULL) { + (comFreeExt)(data); + return; + } + + #ifdef macintosh + if( data != nil ){ + h = RecoverHandle((Ptr) data); + DisposeHandle(h); + } + + #else /* others */ + free(data); + #endif +}