]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_comcryption/lib/comcryptPriv.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_comcryption / lib / comcryptPriv.h
diff --git a/Security/libsecurity_comcryption/lib/comcryptPriv.h b/Security/libsecurity_comcryption/lib/comcryptPriv.h
new file mode 100644 (file)
index 0000000..d99c963
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * 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_*/