--- /dev/null
+/*
+ * Copyright (c) 1997,2011,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@
+ */
+
+
+#ifndef _COMCRYPT_PRIV_H_
+#define _COMCRYPT_PRIV_H_
+
+#include "comcryption.h"
+#include "comDebug.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern comMallocExternFcn *comMallocExt;
+extern comFreeExternFcn *comFreeExt;
+
+/*
+ * type of element in comcryptBuf.queue[]. Making this an unsigned int gives
+ * a slight performance improvement on the i486 platform, but it does use up
+ * more memory.
+ */
+typedef unsigned queueElt;
+
+/*
+ * Enable queue lookahead via comcryptBuf.lookAhead[]. This is currently
+ * just the default value for comcryptBuf.laEnable.
+ */
+#define QUEUE_LOOKAHEAD 1
+
+/*
+ * lookahead queue is bit array if 1, else byte array.
+ * FIXME - this will most likely be a hard-coded 1 for Mac and
+ * dynamically configurable for other platforms.
+ */
+#define QUEUE_LOOKAHEAD_BIT 1
+
+/*
+ * Size of lookAhead buffer in bytes.
+ */
+#if QUEUE_LOOKAHEAD_BIT
+/*
+ * 1 bit per potential queueElt value.
+ */
+#define LOOKAHEAD_SIZE (1 << ((2 * 8) - 3))
+#else /* QUEUE_LOOKAHEAD_BIT */
+/*
+ * One byte per queueElt value; avoids shifts and masks in accessing
+ * array elements at the cost of additional memory.
+ */
+#define LOOKAHEAD_SIZE (1 << (2 * 8))
+#endif /* QUEUE_LOOKAHEAD_BIT */
+
+/*
+ * When true, optimize away the cost of the keynybble() call on a hit
+ * on queue[0].
+ */
+#define SKIP_NIBBLE_ON_QUEUE_0 1
+
+/*
+ * pre-malloc'd buffers, one per level of comcryption. This allows each level
+ * to maintain its own queue state machine as well as its own comcryption
+ * parameters.
+ */
+typedef struct _comcryptBuf {
+ queueElt *queue; // mallocd, QLEN elements
+ unsigned nybbleDex; // index for keynybble()
+ struct _comcryptBuf *nextBuf; // for recursion
+
+ /*
+ * Used to temporarily store bytecode fragments during comcryption and
+ * partial blocks during decomcryption.
+ */
+ unsigned char *codeBuf;
+ unsigned codeBufSize; // malloc'd size of codeBuf
+ unsigned codeBufLength; // valid bytes in codeBuf
+
+ /*
+ * Buffer for two-level comcryption. During comcryption, 2nd level
+ * comcrypted bytecode is placed here. During decomcryption, the result
+ * of decomcrytping the 2nd level bytecode is placed here.
+ */
+ unsigned char *level2Buf;
+ unsigned level2BufSize; // malloc'd size of level2Buf
+
+ /*
+ * comcryption parameters, may (eventually) be different for different
+ * levels. Tweakable, for now, only via private API in comDebug.h.
+ */
+ unsigned f1;
+ unsigned f2;
+ unsigned jmatchThresh; // max avg jmatch for 2 level
+ unsigned minByteCode; // min numByteCodes for 2 level
+
+ /*
+ * Bit map, one bit per potential value in queue[]; 1 means "this value
+ * is somewhere in queue[]"
+ */
+ unsigned char *lookAhead;
+
+ /*
+ * Signature Sequence array - to be Xord with ciphertext
+ * size = MAX_TOKENS
+ */
+ unsigned *sigArray;
+} comcryptBuf;
+
+
+/*
+ * Private struct associated with client's comcryptObj.
+ */
+typedef struct {
+ unsigned char *key;
+ unsigned keybytes; // valid bytes in *key
+ comcryptOptimize optimize; // CCO_SIZE, etc.
+ unsigned char *map;
+ unsigned char *invmap;
+ unsigned version; // from ciphertext
+ unsigned versionBytes; // valid bytes in version;
+ // also nonzero on comcrypt
+ // means version has been
+ // written
+ unsigned spareBytes; // # ciphertext header spare
+ // bytes skipped
+ comcryptBuf cbuf;
+
+ /*
+ * To save a tiny bit of memory, these could/should be bits, but
+ * we examine some of them on every code word, so we'll expand them into
+ * bytes...
+ */
+ unsigned char laEnable; // lookahead enable
+ unsigned char sigSeqEnable; // signature sequence enable
+ unsigned char level2enable; // 2-level comcryption
+
+} comcryptPriv;
+
+
+/*
+ * Block and buffer sizes. Subject to tweaking...
+ */
+#define CC_BLOCK_SIZE 256 /* bytes of plaintext */
+
+/*
+ * For comcryptMaxInBufSize(CCOP_COMCRYPT), if outBufSize exceeds this
+ * threshhold, truncate the max inBufSize so that
+ * inBufSize = 0 mod CC_BLOCK_SIZE.
+ */
+#define INBUF_TRUNC_THRESH (16 * 1024)
+
+/*
+ * Macros to calculate number of token bits and bytes associated with
+ * a quantity of plaintext (in bytes)
+ */
+#define TOKEN_BITS_FROM_PTEXT(pt) ((pt + 1) >> 1)
+#define TOKEN_BYTES_FROM_PTEXT(pt) ((pt + 15) >> 4)
+#define TOKEN_BYTES_FROM_TOKEN_BITS(tb) ((tb + 7) >> 3)
+
+/*
+ * Max number of token bits or code fragments in a block
+ */
+#define MAX_TOKENS (CC_BLOCK_SIZE / 2)
+
+/*
+ * Size of comcryptBuf.queue[].
+ */
+#define QLEN 256
+
+/*
+ * FIXME - some info on these constants?
+ */
+#define F1_DEFAULT 12
+#define F2_DEFAULT 12
+#define ABOVE(F2) ((F2 * QLEN) >> 4)
+
+/*
+ * Constants for obfuscation via signature sequence.
+ */
+#define HASH_Q 19
+#define HASH_PRIME ((1<<HASH_Q)-1) /* Must be prime less than 2^19. */
+#define IN_OFFSET 3 /* Must be in [1,255]. */
+#define OUT_OFFSET 5 /* Must be in [1,255]. */
+
+/*
+ * Ciphertext structure:
+ *
+ * 4 bytes of version
+ * 4 bytes spare
+ * n blocks, format described below
+ */
+#define VERSION_3_Dec_97 0xc0de0003
+#define VERSION_BYTES 4
+#define SPARE_BYTES 4
+#define CTEXT_HDR_SIZE (VERSION_BYTES + SPARE_BYTES)
+
+/*
+ * Format of CBD_SINGLE block
+ *
+ * block description (see CBD_xxx, below)
+ * number of longCodes
+ * number of tokens - optional, absent if CBD_FULL_BLOCK
+ * token array
+ * longCode array
+ * byteCode array - length implied from number of longCodes, tokens
+ *
+ * Format of CBD_DOUBLE block
+ *
+ * block description (see CBD_xxx, below)
+ * number of longCodes
+ * number of tokens - optional, absent if CBD_FULL_BLOCK
+ * token array
+ * longCode array
+ * length of 2nd level comcrypted byte code to follow
+ * 2nd level comcrypted byte code array
+ */
+
+/*
+ * Offsets (block-relative) of ciphertext components. All fields are byte-wide.
+ * This limits block size to < 512 (the limiting case is a whole block of
+ * bytecodes or a whole block of longcodes). Changing the counts to
+ * two bytes would add flexibility and is necessary for block sizes of 512
+ * or greater, but it would cost up to 3 bytes per block.
+ */
+#define CTBO_BLOCK_DESC 0x00 /* descriptor bits, see below */
+#define CTBO_NUM_LONG_CODES 0x01 /* in 16-bit words */
+
+/*
+ * if block[CTBO_BLOCK_DESC] & CBD_FULL_BLOCK, the following byte
+ * is deleted (actually, implied) and subsequent fields are moved
+ * up one byte. This saves one byte per block for most blocks.
+ */
+#define CTBO_NUM_TOKENS 0x02
+
+/*
+ * Offsets of remaining fields not constant; they depend on CBD_FULL_BLOCK and
+ * CBD_SINGLE/CBD_DOUBLE.
+ */
+
+/*
+ * Min block size - blockDesc, numLongCodes, numTokens, one token byte,
+ * one bytecode
+ */
+#define MIN_CBLOCK_SIZE 5 /* min cipherblock size */
+
+/*
+ * Max block size - blockDesc, numLongCodes, full block's tokens, and
+ * a full block of longcodes
+ */
+#define MAX_CBLOCK_SIZE (2 + \
+ TOKEN_BYTES_FROM_PTEXT(CC_BLOCK_SIZE) + \
+ CC_BLOCK_SIZE)
+
+/*
+ * Bits in block[CTBO_BLOCK_DESC]
+ */
+#define CBD_MAGIC 0xd0 /* high nibble must be 0xd */
+#define CBD_MAGIC_MASK 0xf0
+#define CBD_BLOCK_TYPE_MASK 0x01
+#define CBD_SINGLE 0x00 /* single-level comcrypt */
+#define CBD_DOUBLE 0x01 /* double-level comcrypt */
+#define CBD_ODD_MASK 0x02
+#define CBD_ODD 0x02 /* last code maps to single */
+ /* (odd) byte */
+#define CBD_EVEN 0x00
+#define CBD_FULL_BLOCK_MASK 0x04
+#define CBD_FULL_BLOCK 0x04 /* expands to CC_BLOCK_SIZE, also */
+ /* implies no CTBO_NUM_TOKENS byte
+ * in block */
+/*
+ * Defining this non-zero limits effective key size to 40 bits for export
+ */
+#define COMCRYPT_EXPORT_ONLY 0
+#define EXPORT_KEY_SIZE 5 /* in bytes */
+
+/*
+ * Threshholds for performing 2-level comcrypt
+ */
+#define THRESH_2LEVEL_JMATCH_DEF 40 /* max average jmatch */
+#define THRESH_2LEVEL_NUMBYTECODES_DEF 30 /* min number of bytecodes */
+
+
+/*
+ * Private routines in comcryptPriv.c
+ */
+extern void key_perm(
+ const unsigned char *key,
+ int keybytes,
+ unsigned char *map,
+ unsigned char *invmap);
+extern int keybyte(
+ const unsigned char *key,
+ int keybytes,
+ int index);
+extern int keynybble(
+ const unsigned char *key,
+ int keybytes,
+ int index);
+extern void mallocCodeBufs(comcryptBuf *cbufs);
+extern void freeCodeBufs(comcryptBuf *cbufs);
+extern void initCodeBufs(
+ comcryptBuf *cbuf,
+ const unsigned char *key,
+ unsigned keyLen,
+ unsigned char laEnable,
+ unsigned char sigSeqEnable);
+#if 0
+extern void serializeShort(
+ unsigned short s,
+ unsigned char *buf);
+unsigned short deserializeShort(unsigned char *buf);
+#endif /*0*/
+void serializeInt(
+ unsigned i,
+ unsigned char *buf);
+unsigned deserializeInt(unsigned char *buf);
+void initSigSequence(comcryptBuf *cbuf,
+ const unsigned char *key,
+ unsigned keyLen);
+void sigMunge(comcryptBuf *cbuf,
+ const unsigned char *tokenPtr,
+ unsigned numTokens,
+ unsigned char *byteCodePtr,
+ unsigned char *longCodePtr);
+#if 0
+void nextSigWord(comcryptBuf *cbuf,
+ unsigned sigDex, // same as tokenDex
+ unsigned match,
+ unsigned above);
+#endif
+
+#if COM_LA_DEBUG
+extern int testLookAhead(comcryptBuf *cbuf, int i1, int i2);
+extern int initTestLookAhead(comcryptBuf *cbuf);
+#else /*COM_LA_DEBUG*/
+#define testLookAhead(cbuf, i1, i2)
+#define initTestLookAhead(cbuf)
+#endif /* COM_LA_DEBUG */
+
+/*
+ * Routines written as macros solely for performance reasons
+ */
+
+/*
+ * try a couple different mersenne mods...
+ */
+#define MOD_HASH(x) { \
+ while(x > HASH_PRIME) { \
+ x = (x >> HASH_Q) + (x & HASH_PRIME); \
+ } \
+}
+
+/*
+ * Haven't gotten this to work for the Mac yet...
+ */
+#ifdef NeXT
+#define SIG_WORD_INLINE 1
+#else /*NeXT*/
+#define SIG_WORD_INLINE 0
+#endif
+
+#if SIG_WORD_INLINE
+
+static inline void nextSigWord(comcryptBuf *cbuf,
+ unsigned sigDex, // same as tokenDex
+ unsigned match,
+ unsigned above) // (jabove, keyabove) + nibbleDex
+{
+ unsigned offset;
+ unsigned *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;
+ }
+ sigArray[sigDex] = sigArray[sigDex-1] * (above + offset);
+ MOD_HASH(sigArray[sigDex]);
+}
+
+#else /*SIG_WORD_INLINE*/
+
+#define nextSigWord(cbuf, sigDex, match, above) { \
+ unsigned offset = (match ? IN_OFFSET : OUT_OFFSET); \
+ unsigned *sigArray = cbuf->sigArray; \
+ unsigned result = (sigArray[sigDex-1] * (above + offset)); \
+ MOD_HASH(result); \
+ sigArray[sigDex] = result; \
+}
+
+#endif /*SIG_WORD_INLINE*/
+
+/*
+ * Inline serializeShort(), deserializeShort()
+ */
+#define serializeShort(s, buf) \
+ buf[0] = (unsigned char)(s >> 8); \
+ buf[1] = (unsigned char)(s); \
+
+#define deserializeShort(s, buf) \
+ s = ((unsigned short)buf[0]) << 8; \
+ s |= buf[1]; \
+
+
+/*
+ * General purpose macros for accessing bit arrays. Used for accessing
+ * token bits and lookahead array bits if QUEUE_LOOKAHEAD_BIT = 1.
+ */
+#define MARK_BIT_ARRAY(cp, index, val) { \
+ unsigned char bit = 1 << (index & 7); \
+ unsigned char *bytePtr = &cp[index>>3]; \
+ if(val) { \
+ *bytePtr |= bit; \
+ } \
+ else { \
+ *bytePtr &= ~bit; \
+ } \
+}
+#define GET_BIT_ARRAY(cp, index) \
+ (cp[index >> 3] & (1 << (index & 7)))
+
+#define getToken(tokenPtr, tokenDex) \
+ GET_BIT_ARRAY(tokenPtr, tokenDex)
+
+#define updateToken(tokenPtr, tokenDex, tokenBit) \
+ MARK_BIT_ARRAY(tokenPtr, tokenDex, tokenBit)
+
+/*
+ * Macros for accessing lookahead array elements
+ */
+
+#if QUEUE_LOOKAHEAD_BIT
+/*
+ * This way saves memory
+ */
+#define markInQueue(cbuf, codeWord, val) \
+ MARK_BIT_ARRAY(cbuf->lookAhead, codeWord, val)
+
+#define inQueue(cbuf, codeWord) \
+ GET_BIT_ARRAY(cbuf->lookAhead, codeWord)
+
+#else /* QUEUE_LOOKAHEAD_BIT */
+
+/*
+ * This way saves time
+ */
+#define markInQueue(cbuf, codeWord, val) { \
+ cbuf->lookAhead[codeWord] = val; \
+}
+#define inQueue(cbuf, codeWord) (cbuf->lookAhead[codeWord])
+
+#endif /* QUEUE_LOOKAHEAD_BIT */
+
+void *ascMalloc(unsigned size);
+void ascFree(void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_COMCRYPT_PRIV_H_*/