1/* 2 File: comcryptPriv.h 3 4 Contains: private typedefs and #defines for comcryption library. 5 6 Written by: Doug Mitchell 7 8 Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved. 9 10 Change History (most recent first): 11 12 05/28/98 dpm Added platform-dependent ascMalloc and ascFree 13 12/08/97 dpm Added Signature Sequence mechanism. 14 12/03/97 dpm Added queue lookahead; various optimizations. 15 11/13/97 dpm Created; broke out from comcryption.c 16 17 To Do: 18*/ 19 20#ifndef _COMCRYPT_PRIV_H_ 21#define _COMCRYPT_PRIV_H_ 22 23#include "comcryption.h" 24#include "comDebug.h" 25 26#ifdef __cplusplus 27extern "C" { 28#endif 29 30extern comMallocExternFcn *comMallocExt; 31extern comFreeExternFcn *comFreeExt; 32 33/* 34 * type of element in comcryptBuf.queue[]. Making this an unsigned int gives 35 * a slight performance improvement on the i486 platform, but it does use up 36 * more memory. 37 */ 38typedef unsigned queueElt; 39 40/* 41 * Enable queue lookahead via comcryptBuf.lookAhead[]. This is currently 42 * just the default value for comcryptBuf.laEnable. 43 */ 44#define QUEUE_LOOKAHEAD 1 45 46/* 47 * lookahead queue is bit array if 1, else byte array. 48 * FIXME - this will most likely be a hard-coded 1 for Mac and 49 * dynamically configurable for other platforms. 50 */ 51#define QUEUE_LOOKAHEAD_BIT 1 52 53/* 54 * Size of lookAhead buffer in bytes. 55 */ 56#if QUEUE_LOOKAHEAD_BIT 57/* 58 * 1 bit per potential queueElt value. 59 */ 60#define LOOKAHEAD_SIZE (1 << ((2 * 8) - 3)) 61#else /* QUEUE_LOOKAHEAD_BIT */ 62/* 63 * One byte per queueElt value; avoids shifts and masks in accessing 64 * array elements at the cost of additional memory. 65 */ 66#define LOOKAHEAD_SIZE (1 << (2 * 8)) 67#endif /* QUEUE_LOOKAHEAD_BIT */ 68 69/* 70 * When true, optimize away the cost of the keynybble() call on a hit 71 * on queue[0]. 72 */ 73#define SKIP_NIBBLE_ON_QUEUE_0 1 74 75/* 76 * pre-malloc'd buffers, one per level of comcryption. This allows each level 77 * to maintain its own queue state machine as well as its own comcryption 78 * parameters. 79 */ 80typedef struct _comcryptBuf { 81 queueElt *queue; // mallocd, QLEN elements 82 unsigned nybbleDex; // index for keynybble() 83 struct _comcryptBuf *nextBuf; // for recursion 84 85 /* 86 * Used to temporarily store bytecode fragments during comcryption and 87 * partial blocks during decomcryption. 88 */ 89 unsigned char *codeBuf; 90 unsigned codeBufSize; // malloc'd size of codeBuf 91 unsigned codeBufLength; // valid bytes in codeBuf 92 93 /* 94 * Buffer for two-level comcryption. During comcryption, 2nd level 95 * comcrypted bytecode is placed here. During decomcryption, the result 96 * of decomcrytping the 2nd level bytecode is placed here. 97 */ 98 unsigned char *level2Buf; 99 unsigned level2BufSize; // malloc'd size of level2Buf 100 101 /* 102 * comcryption parameters, may (eventually) be different for different 103 * levels. Tweakable, for now, only via private API in comDebug.h. 104 */ 105 unsigned f1; 106 unsigned f2; 107 unsigned jmatchThresh; // max avg jmatch for 2 level 108 unsigned minByteCode; // min numByteCodes for 2 level 109 110 /* 111 * Bit map, one bit per potential value in queue[]; 1 means "this value 112 * is somewhere in queue[]" 113 */ 114 unsigned char *lookAhead; 115 116 /* 117 * Signature Sequence array - to be Xord with ciphertext 118 * size = MAX_TOKENS 119 */ 120 unsigned *sigArray; 121} comcryptBuf; 122 123 124/* 125 * Private struct associated with client's comcryptObj. 126 */ 127typedef struct { 128 unsigned char *key; 129 unsigned keybytes; // valid bytes in *key 130 comcryptOptimize optimize; // CCO_SIZE, etc. 131 unsigned char *map; 132 unsigned char *invmap; 133 unsigned version; // from ciphertext 134 unsigned versionBytes; // valid bytes in version; 135 // also nonzero on comcrypt 136 // means version has been 137 // written 138 unsigned spareBytes; // # ciphertext header spare 139 // bytes skipped 140 comcryptBuf cbuf; 141 142 /* 143 * To save a tiny bit of memory, these could/should be bits, but 144 * we examine some of them on every code word, so we'll expand them into 145 * bytes... 146 */ 147 unsigned char laEnable; // lookahead enable 148 unsigned char sigSeqEnable; // signature sequence enable 149 unsigned char level2enable; // 2-level comcryption 150 151} comcryptPriv; 152 153 154/* 155 * Block and buffer sizes. Subject to tweaking... 156 */ 157#define CC_BLOCK_SIZE 256 /* bytes of plaintext */ 158 159/* 160 * For comcryptMaxInBufSize(CCOP_COMCRYPT), if outBufSize exceeds this 161 * threshhold, truncate the max inBufSize so that 162 * inBufSize = 0 mod CC_BLOCK_SIZE. 163 */ 164#define INBUF_TRUNC_THRESH (16 * 1024) 165 166/* 167 * Macros to calculate number of token bits and bytes associated with 168 * a quantity of plaintext (in bytes) 169 */ 170#define TOKEN_BITS_FROM_PTEXT(pt) ((pt + 1) >> 1) 171#define TOKEN_BYTES_FROM_PTEXT(pt) ((pt + 15) >> 4) 172#define TOKEN_BYTES_FROM_TOKEN_BITS(tb) ((tb + 7) >> 3) 173 174/* 175 * Max number of token bits or code fragments in a block 176 */ 177#define MAX_TOKENS (CC_BLOCK_SIZE / 2) 178 179/* 180 * Size of comcryptBuf.queue[]. 181 */ 182#define QLEN 256 183 184/* 185 * FIXME - some info on these constants? 186 */ 187#define F1_DEFAULT 12 188#define F2_DEFAULT 12 189#define ABOVE(F2) ((F2 * QLEN) >> 4) 190 191/* 192 * Constants for obfuscation via signature sequence. 193 */ 194#define HASH_Q 19 195#define HASH_PRIME ((1<<HASH_Q)-1) /* Must be prime less than 2^19. */ 196#define IN_OFFSET 3 /* Must be in [1,255]. */ 197#define OUT_OFFSET 5 /* Must be in [1,255]. */ 198 199/* 200 * Ciphertext structure: 201 * 202 * 4 bytes of version 203 * 4 bytes spare 204 * n blocks, format described below 205 */ 206#define VERSION_3_Dec_97 0xc0de0003 207#define VERSION_BYTES 4 208#define SPARE_BYTES 4 209#define CTEXT_HDR_SIZE (VERSION_BYTES + SPARE_BYTES) 210 211/* 212 * Format of CBD_SINGLE block 213 * 214 * block description (see CBD_xxx, below) 215 * number of longCodes 216 * number of tokens - optional, absent if CBD_FULL_BLOCK 217 * token array 218 * longCode array 219 * byteCode array - length implied from number of longCodes, tokens 220 * 221 * Format of CBD_DOUBLE block 222 * 223 * block description (see CBD_xxx, below) 224 * number of longCodes 225 * number of tokens - optional, absent if CBD_FULL_BLOCK 226 * token array 227 * longCode array 228 * length of 2nd level comcrypted byte code to follow 229 * 2nd level comcrypted byte code array 230 */ 231 232/* 233 * Offsets (block-relative) of ciphertext components. All fields are byte-wide. 234 * This limits block size to < 512 (the limiting case is a whole block of 235 * bytecodes or a whole block of longcodes). Changing the counts to 236 * two bytes would add flexibility and is necessary for block sizes of 512 237 * or greater, but it would cost up to 3 bytes per block. 238 */ 239#define CTBO_BLOCK_DESC 0x00 /* descriptor bits, see below */ 240#define CTBO_NUM_LONG_CODES 0x01 /* in 16-bit words */ 241 242/* 243 * if block[CTBO_BLOCK_DESC] & CBD_FULL_BLOCK, the following byte 244 * is deleted (actually, implied) and subsequent fields are moved 245 * up one byte. This saves one byte per block for most blocks. 246 */ 247#define CTBO_NUM_TOKENS 0x02 248 249/* 250 * Offsets of remaining fields not constant; they depend on CBD_FULL_BLOCK and 251 * CBD_SINGLE/CBD_DOUBLE. 252 */ 253 254/* 255 * Min block size - blockDesc, numLongCodes, numTokens, one token byte, 256 * one bytecode 257 */ 258#define MIN_CBLOCK_SIZE 5 /* min cipherblock size */ 259 260/* 261 * Max block size - blockDesc, numLongCodes, full block's tokens, and 262 * a full block of longcodes 263 */ 264#define MAX_CBLOCK_SIZE (2 + \ 265 TOKEN_BYTES_FROM_PTEXT(CC_BLOCK_SIZE) + \ 266 CC_BLOCK_SIZE) 267 268/* 269 * Bits in block[CTBO_BLOCK_DESC] 270 */ 271#define CBD_MAGIC 0xd0 /* high nibble must be 0xd */ 272#define CBD_MAGIC_MASK 0xf0 273#define CBD_BLOCK_TYPE_MASK 0x01 274#define CBD_SINGLE 0x00 /* single-level comcrypt */ 275#define CBD_DOUBLE 0x01 /* double-level comcrypt */ 276#define CBD_ODD_MASK 0x02 277#define CBD_ODD 0x02 /* last code maps to single */ 278 /* (odd) byte */ 279#define CBD_EVEN 0x00 280#define CBD_FULL_BLOCK_MASK 0x04 281#define CBD_FULL_BLOCK 0x04 /* expands to CC_BLOCK_SIZE, also */ 282 /* implies no CTBO_NUM_TOKENS byte 283 * in block */ 284/* 285 * Defining this non-zero limits effective key size to 40 bits for export 286 */ 287#define COMCRYPT_EXPORT_ONLY 0 288#define EXPORT_KEY_SIZE 5 /* in bytes */ 289 290/* 291 * Threshholds for performing 2-level comcrypt 292 */ 293#define THRESH_2LEVEL_JMATCH_DEF 40 /* max average jmatch */ 294#define THRESH_2LEVEL_NUMBYTECODES_DEF 30 /* min number of bytecodes */ 295 296 297/* 298 * Private routines in comcryptPriv.c 299 */ 300extern void key_perm( 301 const unsigned char *key, 302 int keybytes, 303 unsigned char *map, 304 unsigned char *invmap); 305extern int keybyte( 306 const unsigned char *key, 307 int keybytes, 308 int index); 309extern int keynybble( 310 const unsigned char *key, 311 int keybytes, 312 int index); 313extern void mallocCodeBufs(comcryptBuf *cbufs); 314extern void freeCodeBufs(comcryptBuf *cbufs); 315extern void initCodeBufs( 316 comcryptBuf *cbuf, 317 const unsigned char *key, 318 unsigned keyLen, 319 unsigned char laEnable, 320 unsigned char sigSeqEnable); 321#if 0 322extern void serializeShort( 323 unsigned short s, 324 unsigned char *buf); 325unsigned short deserializeShort(unsigned char *buf); 326#endif /*0*/ 327void serializeInt( 328 unsigned i, 329 unsigned char *buf); 330unsigned deserializeInt(unsigned char *buf); 331void initSigSequence(comcryptBuf *cbuf, 332 const unsigned char *key, 333 unsigned keyLen); 334void sigMunge(comcryptBuf *cbuf, 335 const unsigned char *tokenPtr, 336 unsigned numTokens, 337 unsigned char *byteCodePtr, 338 unsigned char *longCodePtr); 339#if 0 340void nextSigWord(comcryptBuf *cbuf, 341 unsigned sigDex, // same as tokenDex 342 unsigned match, 343 unsigned above); 344#endif 345 346#if COM_LA_DEBUG 347extern int testLookAhead(comcryptBuf *cbuf, int i1, int i2); 348extern int initTestLookAhead(comcryptBuf *cbuf); 349#else /*COM_LA_DEBUG*/ 350#define testLookAhead(cbuf, i1, i2) 351#define initTestLookAhead(cbuf) 352#endif /* COM_LA_DEBUG */ 353 354/* 355 * Routines written as macros solely for performance reasons 356 */ 357 358/* 359 * try a couple different mersenne mods... 360 */ 361#define MOD_HASH(x) { \ 362 while(x > HASH_PRIME) { \ 363 x = (x >> HASH_Q) + (x & HASH_PRIME); \ 364 } \ 365} 366 367/* 368 * Haven't gotten this to work for the Mac yet... 369 */ 370#ifdef NeXT 371#define SIG_WORD_INLINE 1 372#else /*NeXT*/ 373#define SIG_WORD_INLINE 0 374#endif 375 376#if SIG_WORD_INLINE 377 378static inline void nextSigWord(comcryptBuf *cbuf, 379 unsigned sigDex, // same as tokenDex 380 unsigned match, 381 unsigned above) // (jabove, keyabove) + nibbleDex 382{ 383 unsigned offset; 384 unsigned *sigArray = cbuf->sigArray; 385 386 #if COM_DEBUG 387 if(sigDex == 0) { 388 printf("nextSigWord underflow\n"); 389 exit(1); 390 } 391 if(sigDex > MAX_TOKENS) { 392 printf("nextSigWord overflow\n"); 393 exit(1); 394 } 395 #endif 396 397 if(match) { 398 offset = IN_OFFSET; 399 } 400 else { 401 offset = OUT_OFFSET; 402 } 403 sigArray[sigDex] = sigArray[sigDex-1] * (above + offset); 404 MOD_HASH(sigArray[sigDex]); 405} 406 407#else /*SIG_WORD_INLINE*/ 408 409#define nextSigWord(cbuf, sigDex, match, above) { \ 410 unsigned offset = (match ? IN_OFFSET : OUT_OFFSET); \ 411 unsigned *sigArray = cbuf->sigArray; \ 412 unsigned result = (sigArray[sigDex-1] * (above + offset)); \ 413 MOD_HASH(result); \ 414 sigArray[sigDex] = result; \ 415} 416 417#endif /*SIG_WORD_INLINE*/ 418 419/* 420 * Inline serializeShort(), deserializeShort() 421 */ 422#define serializeShort(s, buf) \ 423 buf[0] = (unsigned char)(s >> 8); \ 424 buf[1] = (unsigned char)(s); \ 425 426#define deserializeShort(s, buf) \ 427 s = ((unsigned short)buf[0]) << 8; \ 428 s |= buf[1]; \ 429 430 431/* 432 * General purpose macros for accessing bit arrays. Used for accessing 433 * token bits and lookahead array bits if QUEUE_LOOKAHEAD_BIT = 1. 434 */ 435#define MARK_BIT_ARRAY(cp, index, val) { \ 436 unsigned char bit = 1 << (index & 7); \ 437 unsigned char *bytePtr = &cp[index>>3]; \ 438 if(val) { \ 439 *bytePtr |= bit; \ 440 } \ 441 else { \ 442 *bytePtr &= ~bit; \ 443 } \ 444} 445#define GET_BIT_ARRAY(cp, index) \ 446 (cp[index >> 3] & (1 << (index & 7))) 447 448#define getToken(tokenPtr, tokenDex) \ 449 GET_BIT_ARRAY(tokenPtr, tokenDex) 450 451#define updateToken(tokenPtr, tokenDex, tokenBit) \ 452 MARK_BIT_ARRAY(tokenPtr, tokenDex, tokenBit) 453 454/* 455 * Macros for accessing lookahead array elements 456 */ 457 458#if QUEUE_LOOKAHEAD_BIT 459/* 460 * This way saves memory 461 */ 462#define markInQueue(cbuf, codeWord, val) \ 463 MARK_BIT_ARRAY(cbuf->lookAhead, codeWord, val) 464 465#define inQueue(cbuf, codeWord) \ 466 GET_BIT_ARRAY(cbuf->lookAhead, codeWord) 467 468#else /* QUEUE_LOOKAHEAD_BIT */ 469 470/* 471 * This way saves time 472 */ 473#define markInQueue(cbuf, codeWord, val) { \ 474 cbuf->lookAhead[codeWord] = val; \ 475} 476#define inQueue(cbuf, codeWord) (cbuf->lookAhead[codeWord]) 477 478#endif /* QUEUE_LOOKAHEAD_BIT */ 479 480void *ascMalloc(unsigned size); 481void ascFree(void *data); 482 483#ifdef __cplusplus 484} 485#endif 486 487#endif /*_COMCRYPT_PRIV_H_*/ 488