]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_comcryption/lib/comcryptPriv.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_comcryption / lib / comcryptPriv.c
diff --git a/Security/libsecurity_comcryption/lib/comcryptPriv.c b/Security/libsecurity_comcryption/lib/comcryptPriv.c
new file mode 100644 (file)
index 0000000..873b32c
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef macintosh
+#include <MacMemory.h>
+#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; ctr<keylen; ctr++) {
+               x = (x * (key[ctr] + (ctr & HASH_REDUCE) + 1)) % HASH_PRIME;
+       }
+       return x;
+}
+
+void mallocCodeBufs(comcryptBuf *cbuf)
+{
+       /*
+        * calculate required buffer sizes. 
+        *
+        * Assume max required codeBuf size is the max size of ciphertext needed
+        * to decrypt one block of plaintext.
+        */
+       cbuf->codeBufSize = 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; ct<QLEN; ct++) {
+               /*
+                * New queue init 23 Dec - init from khash
+                */
+               unsigned short sbyte = ct ^ khash;
+               qval = (sbyte << 8) | ct;
+               cbuf->queue[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; i<QLEN; i++) {
+               if(!inQueue(cbuf, cbuf->queue[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; byte<LOOKAHEAD_SIZE; byte++) {
+               for(bit=1; bit!=0; bit<<=1) {
+                       if(la[byte] & bit) {
+                               /*
+                                * in lookahead, make sure it's in queue[]
+                                */
+                               int i;
+                               int found = 0;
+
+                               for(i=0; i<QLEN; i++) {
+                                       if(cbuf->queue[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; j<keyLen; j++) {
+               seed += key[j];
+    }
+    seed %= HASH_PRIME;
+    if(seed == 0) {
+               seed = IN_OFFSET;
+       }
+       cbuf->sigArray[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; token<numTokens; token++) {
+               sig = cbuf->sigArray[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
+}