/* * 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_*/