4 Contains: private routines for comcryption library.
6 Written by: Doug Mitchell
8 Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved.
10 Change History (most recent first):
12 05/28/98 dpm Added platform-dependent ascMalloc and ascFree
13 12/23/97 dpm Added keyHash(), used result to initialize
15 12/18/97 dpm Improved queue initialization.
16 12/03/97 dpm Added queue lookahead; various optimizations.
17 11/13/97 dpm Created; broke out from comcryption.c
22 #include "comcryptPriv.h"
27 #include <MacMemory.h>
30 /* if NULL, use our own */
31 comMallocExternFcn
*comMallocExt
= NULL
;
32 comFreeExternFcn
*comFreeExt
= NULL
;
39 memset(&_comStats
, 0, sizeof(comStats
));
42 void getComStats(comStats
*stats
)
49 #define incrComStat(stat, num)
54 * Generate a symbol permutation from the key.
57 const unsigned char *key
,
60 unsigned char *invmap
)
64 for(sum
= 0, j
= 0; j
< keybytes
; j
++) {
67 for(j
=0; j
< 256; j
++) {
70 for(j
=0; j
< 255; j
++) {
71 i
= (key
[j
% keybytes
] + j
*sum
) & 0xff;
76 for(j
=0; j
<256; j
++) {
82 const unsigned char *key
,
86 return((int) key
[index
% keybytes
]);
90 const unsigned char *key
,
94 int i
= index
% (2*keybytes
);
97 j
= key
[i
>>1]; /* Which byte. */
98 if(i
& 1) j
>>= 4; /* Which nybble. */
107 #define HASH_REDUCE 1023
109 static unsigned keyHash(const unsigned char *key
, unsigned keylen
)
111 unsigned x
= HASH_SEED
; /* Any seed in [1,p-1]. Like SEED = 3. */
114 for(ctr
=0; ctr
<keylen
; ctr
++) {
115 x
= (x
* (key
[ctr
] + (ctr
& HASH_REDUCE
) + 1)) % HASH_PRIME
;
120 void mallocCodeBufs(comcryptBuf
*cbuf
)
123 * calculate required buffer sizes.
125 * Assume max required codeBuf size is the max size of ciphertext needed
126 * to decrypt one block of plaintext.
128 cbuf
->codeBufSize
= comcryptMaxOutBufSize(NULL
,
132 cbuf
->codeBuf
= (unsigned char *)ascMalloc(cbuf
->codeBufSize
);
135 * max size needed for level2Buf is the MaxOutBufSize of comcrypting
136 * a whole block of byte code. Note we assume that MaxOutBufSize(n) >= n.
138 cbuf
->level2BufSize
= comcryptMaxOutBufSize(NULL
,
139 MAX_TOKENS
, // one byte per token
142 cbuf
->level2Buf
= (unsigned char *)ascMalloc(cbuf
->level2BufSize
);
144 cbuf
->queue
= (queueElt
*)ascMalloc(sizeof(queueElt
) * QLEN
);
148 * Might want to do this dynamically, though that requires the malloc
149 * of the lookAhead buffer to be done in initCodeBufs(), not here (at
150 * comcryptAlloc() time).
152 * FIXME : should do the malloc of lookAhead buffer lazily for
155 cbuf
->lookAhead
= (unsigned char *)ascMalloc(LOOKAHEAD_SIZE
);
156 #else /* QUEUE_LOOKAHEAD */
157 cbuf
->lookAhead
= NULL
;
158 #endif /* QUEUE_LOOKAHEAD */
161 * This maybe should also be done dynamically, lazily...
163 cbuf
->sigArray
= (unsigned *)ascMalloc((MAX_TOKENS
+ 1) * sizeof(unsigned));
168 const unsigned char *key
,
170 unsigned char laEnable
,
171 unsigned char sigSeqEnable
)
175 unsigned char khash
= (unsigned char)keyHash(key
, keyLen
);
177 cbuf
->nybbleDex
= khash
;
180 memset(cbuf
->lookAhead
, 0, LOOKAHEAD_SIZE
);
183 laprintf(("initing queue and lookahead\n"));
185 for(ct
=0; ct
<QLEN
; ct
++) {
187 * New queue init 23 Dec - init from khash
189 unsigned short sbyte
= ct
^ khash
;
190 qval
= (sbyte
<< 8) | ct
;
191 cbuf
->queue
[ct
] = qval
;
193 markInQueue(cbuf
, qval
, 1);
196 // note cbuf->nybbleDex = khash on return...
198 cbuf
->f1
= F1_DEFAULT
;
199 cbuf
->f2
= F2_DEFAULT
;
200 cbuf
->jmatchThresh
= THRESH_2LEVEL_JMATCH_DEF
;
201 cbuf
->minByteCode
= THRESH_2LEVEL_NUMBYTECODES_DEF
;
203 initSigSequence(cbuf
, key
, keyLen
);
207 void freeCodeBufs(comcryptBuf
*cbuf
)
209 if(cbuf
->queue
!= NULL
) {
210 ascFree(cbuf
->queue
);
212 if(cbuf
->codeBuf
!= NULL
) {
213 ascFree(cbuf
->codeBuf
);
215 if(cbuf
->level2Buf
!= NULL
) {
216 ascFree(cbuf
->level2Buf
);
218 if(cbuf
->nextBuf
!= NULL
) {
219 freeCodeBufs(cbuf
->nextBuf
);
220 ascFree(cbuf
->nextBuf
);
221 cbuf
->nextBuf
= NULL
;
223 if(cbuf
->lookAhead
!= NULL
) {
224 ascFree(cbuf
->lookAhead
);
226 if(cbuf
->sigArray
!= NULL
) {
227 ascFree(cbuf
->sigArray
);
235 buf
[0] = (unsigned char)(i
>> 24);
236 buf
[1] = (unsigned char)(i
>> 16);
237 buf
[2] = (unsigned char)(i
>> 8);
238 buf
[3] = (unsigned char)(i
& 0xff);
241 unsigned deserializeInt(unsigned char *buf
)
245 i
= ((unsigned)buf
[0]) << 24;
246 i
|= ((unsigned)buf
[1]) << 16;
247 i
|= ((unsigned)buf
[2]) << 8;
254 unsigned getF1(comcryptObj cobj
)
256 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
258 return cpriv
->cbuf
.f1
;
261 void setF1(comcryptObj cobj
, unsigned f1
)
263 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
266 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
267 cpriv
->cbuf
.nextBuf
->f1
= f1
;
271 unsigned getF2(comcryptObj cobj
)
273 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
275 return cpriv
->cbuf
.f2
;
278 void setF2(comcryptObj cobj
, unsigned f2
)
280 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
283 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
284 cpriv
->cbuf
.nextBuf
->f2
= f2
;
288 unsigned getJmatchThresh(comcryptObj cobj
)
290 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
292 return cpriv
->cbuf
.jmatchThresh
;
295 void setJmatchThresh(comcryptObj cobj
, unsigned jmatchThresh
)
297 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
299 cpriv
->cbuf
.jmatchThresh
= jmatchThresh
;
300 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
301 cpriv
->cbuf
.nextBuf
->jmatchThresh
= jmatchThresh
;
305 unsigned getMinByteCode(comcryptObj cobj
)
307 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
309 return cpriv
->cbuf
.minByteCode
;
312 void setMinByteCode(comcryptObj cobj
, unsigned minByteCode
)
314 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
316 cpriv
->cbuf
.minByteCode
= minByteCode
;
317 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
318 cpriv
->cbuf
.nextBuf
->minByteCode
= minByteCode
;
322 #endif /*COM_PARAM_ENABLE*/
328 * Verify integrity of lookahead w.r.t. queue.
330 int testLookAhead(comcryptBuf
*cbuf
, int i1
, int i2
)
334 if(!cbuf
->laEnable
) {
337 for(i
=0; i
<QLEN
; i
++) {
338 if(!inQueue(cbuf
, cbuf
->queue
[i
])) {
339 printf("aaagh, corrupted lookahead - in queue[], !inQueue()\n");
340 printf("i=0x%x i1=0x%x i2=0x%x\n",
346 //return initTestLookAhead(cbuf);
350 int initTestLookAhead(comcryptBuf
*cbuf
)
352 #if QUEUE_LOOKAHEAD_BIT
354 unsigned codeWord
= 0;
357 unsigned char *la
= cbuf
->lookAhead
;
359 for(byte
=0; byte
<LOOKAHEAD_SIZE
; byte
++) {
360 for(bit
=1; bit
!=0; bit
<<=1) {
363 * in lookahead, make sure it's in queue[]
368 for(i
=0; i
<QLEN
; i
++) {
369 if(cbuf
->queue
[i
] == codeWord
) {
375 printf("***corrupted init lookahead - in l.a., "
377 printf("codeWord 0x%x\n", codeWord
);
386 #endif /* QUEUE_LOOKAHEAD_BIT */
390 #endif /* COM_LA_DEBUG */
392 void initSigSequence(comcryptBuf
*cbuf
,
393 const unsigned char *key
,
396 unsigned seed
= IN_OFFSET
;
399 for(j
=0; j
<keyLen
; j
++) {
406 cbuf
->sigArray
[0] = (unsigned short)seed
;
411 * Called once per token bit, after processing the token.
413 void nextSigWord(comcryptBuf
*cbuf
,
414 unsigned sigDex
, // same as tokenDex
416 unsigned above
) // jabove, keyabove
419 unsigned short *sigArray
= cbuf
->sigArray
;
423 printf("nextSigWord underflow\n");
426 if(sigDex
> MAX_TOKENS
) {
427 printf("nextSigWord overflow\n");
439 sigArray
[sigDex
] = (sigArray
[sigDex
-1] * (above
+ offset
)) % HASH_PRIME
;
445 * Obfuscate a block of ciphertext.
447 void sigMunge(comcryptBuf
*cbuf
,
448 const unsigned char *tokenPtr
,
450 unsigned char *byteCodePtr
,
451 unsigned char *longCodePtr
)
453 unsigned char tokenBit
= 0x01;
457 for(token
=0; token
<numTokens
; token
++) {
458 sig
= cbuf
->sigArray
[token
];
459 if(*tokenPtr
& tokenBit
) {
460 /* no match - munge longCode - written MSB first */
461 *longCodePtr
++ ^= (unsigned char)(sig
>> 8);
462 *longCodePtr
++ ^= (unsigned char)sig
;
465 /* match - munge byteCode */
466 *byteCodePtr
++ ^= (unsigned char)sig
;
478 * All this can be optimized and tailored to specific platforms, of course...
481 void *ascMalloc(unsigned size
)
491 if(comMallocExt
!= NULL
) {
492 return (comMallocExt
)(size
);
500 h
= NewHandleSys(size
); // system heap is not paged
502 HLockHi(h
); // will move low in system heap
504 if( err
!= errSecSuccess
) break;
507 if( err
!= errSecSuccess
){
517 void ascFree(void *data
)
523 if(comFreeExt
!= NULL
) {
530 h
= RecoverHandle((Ptr
) data
);