2 * Copyright (c) 1997,2011,2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "comcryptPriv.h"
30 #include <MacMemory.h>
33 /* if NULL, use our own */
34 comMallocExternFcn
*comMallocExt
= NULL
;
35 comFreeExternFcn
*comFreeExt
= NULL
;
42 memset(&_comStats
, 0, sizeof(comStats
));
45 void getComStats(comStats
*stats
)
52 #define incrComStat(stat, num)
57 * Generate a symbol permutation from the key.
60 const unsigned char *key
,
63 unsigned char *invmap
)
67 for(sum
= 0, j
= 0; j
< keybytes
; j
++) {
70 for(j
=0; j
< 256; j
++) {
73 for(j
=0; j
< 255; j
++) {
74 i
= (key
[j
% keybytes
] + j
*sum
) & 0xff;
79 for(j
=0; j
<256; j
++) {
85 const unsigned char *key
,
89 return((int) key
[index
% keybytes
]);
93 const unsigned char *key
,
97 int i
= index
% (2*keybytes
);
100 j
= key
[i
>>1]; /* Which byte. */
101 if(i
& 1) j
>>= 4; /* Which nybble. */
110 #define HASH_REDUCE 1023
112 static unsigned keyHash(const unsigned char *key
, unsigned keylen
)
114 unsigned x
= HASH_SEED
; /* Any seed in [1,p-1]. Like SEED = 3. */
117 for(ctr
=0; ctr
<keylen
; ctr
++) {
118 x
= (x
* (key
[ctr
] + (ctr
& HASH_REDUCE
) + 1)) % HASH_PRIME
;
123 void mallocCodeBufs(comcryptBuf
*cbuf
)
126 * calculate required buffer sizes.
128 * Assume max required codeBuf size is the max size of ciphertext needed
129 * to decrypt one block of plaintext.
131 cbuf
->codeBufSize
= comcryptMaxOutBufSize(NULL
,
135 cbuf
->codeBuf
= (unsigned char *)ascMalloc(cbuf
->codeBufSize
);
138 * max size needed for level2Buf is the MaxOutBufSize of comcrypting
139 * a whole block of byte code. Note we assume that MaxOutBufSize(n) >= n.
141 cbuf
->level2BufSize
= comcryptMaxOutBufSize(NULL
,
142 MAX_TOKENS
, // one byte per token
145 cbuf
->level2Buf
= (unsigned char *)ascMalloc(cbuf
->level2BufSize
);
147 cbuf
->queue
= (queueElt
*)ascMalloc(sizeof(queueElt
) * QLEN
);
151 * Might want to do this dynamically, though that requires the malloc
152 * of the lookAhead buffer to be done in initCodeBufs(), not here (at
153 * comcryptAlloc() time).
155 * FIXME : should do the malloc of lookAhead buffer lazily for
158 cbuf
->lookAhead
= (unsigned char *)ascMalloc(LOOKAHEAD_SIZE
);
159 #else /* QUEUE_LOOKAHEAD */
160 cbuf
->lookAhead
= NULL
;
161 #endif /* QUEUE_LOOKAHEAD */
164 * This maybe should also be done dynamically, lazily...
166 cbuf
->sigArray
= (unsigned *)ascMalloc((MAX_TOKENS
+ 1) * sizeof(unsigned));
171 const unsigned char *key
,
173 unsigned char laEnable
,
174 unsigned char sigSeqEnable
)
178 unsigned char khash
= (unsigned char)keyHash(key
, keyLen
);
180 cbuf
->nybbleDex
= khash
;
183 memset(cbuf
->lookAhead
, 0, LOOKAHEAD_SIZE
);
186 laprintf(("initing queue and lookahead\n"));
188 for(ct
=0; ct
<QLEN
; ct
++) {
190 * New queue init 23 Dec - init from khash
192 unsigned short sbyte
= ct
^ khash
;
193 qval
= (sbyte
<< 8) | ct
;
194 cbuf
->queue
[ct
] = qval
;
196 markInQueue(cbuf
, qval
, 1);
199 // note cbuf->nybbleDex = khash on return...
201 cbuf
->f1
= F1_DEFAULT
;
202 cbuf
->f2
= F2_DEFAULT
;
203 cbuf
->jmatchThresh
= THRESH_2LEVEL_JMATCH_DEF
;
204 cbuf
->minByteCode
= THRESH_2LEVEL_NUMBYTECODES_DEF
;
206 initSigSequence(cbuf
, key
, keyLen
);
210 void freeCodeBufs(comcryptBuf
*cbuf
)
212 if(cbuf
->queue
!= NULL
) {
213 ascFree(cbuf
->queue
);
215 if(cbuf
->codeBuf
!= NULL
) {
216 ascFree(cbuf
->codeBuf
);
218 if(cbuf
->level2Buf
!= NULL
) {
219 ascFree(cbuf
->level2Buf
);
221 if(cbuf
->nextBuf
!= NULL
) {
222 freeCodeBufs(cbuf
->nextBuf
);
223 ascFree(cbuf
->nextBuf
);
224 cbuf
->nextBuf
= NULL
;
226 if(cbuf
->lookAhead
!= NULL
) {
227 ascFree(cbuf
->lookAhead
);
229 if(cbuf
->sigArray
!= NULL
) {
230 ascFree(cbuf
->sigArray
);
238 buf
[0] = (unsigned char)(i
>> 24);
239 buf
[1] = (unsigned char)(i
>> 16);
240 buf
[2] = (unsigned char)(i
>> 8);
241 buf
[3] = (unsigned char)(i
& 0xff);
244 unsigned deserializeInt(unsigned char *buf
)
248 i
= ((unsigned)buf
[0]) << 24;
249 i
|= ((unsigned)buf
[1]) << 16;
250 i
|= ((unsigned)buf
[2]) << 8;
257 unsigned getF1(comcryptObj cobj
)
259 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
261 return cpriv
->cbuf
.f1
;
264 void setF1(comcryptObj cobj
, unsigned f1
)
266 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
269 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
270 cpriv
->cbuf
.nextBuf
->f1
= f1
;
274 unsigned getF2(comcryptObj cobj
)
276 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
278 return cpriv
->cbuf
.f2
;
281 void setF2(comcryptObj cobj
, unsigned f2
)
283 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
286 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
287 cpriv
->cbuf
.nextBuf
->f2
= f2
;
291 unsigned getJmatchThresh(comcryptObj cobj
)
293 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
295 return cpriv
->cbuf
.jmatchThresh
;
298 void setJmatchThresh(comcryptObj cobj
, unsigned jmatchThresh
)
300 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
302 cpriv
->cbuf
.jmatchThresh
= jmatchThresh
;
303 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
304 cpriv
->cbuf
.nextBuf
->jmatchThresh
= jmatchThresh
;
308 unsigned getMinByteCode(comcryptObj cobj
)
310 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
312 return cpriv
->cbuf
.minByteCode
;
315 void setMinByteCode(comcryptObj cobj
, unsigned minByteCode
)
317 comcryptPriv
*cpriv
= (comcryptPriv
*)cobj
;
319 cpriv
->cbuf
.minByteCode
= minByteCode
;
320 if(cpriv
->cbuf
.nextBuf
!= NULL
) {
321 cpriv
->cbuf
.nextBuf
->minByteCode
= minByteCode
;
325 #endif /*COM_PARAM_ENABLE*/
331 * Verify integrity of lookahead w.r.t. queue.
333 int testLookAhead(comcryptBuf
*cbuf
, int i1
, int i2
)
337 if(!cbuf
->laEnable
) {
340 for(i
=0; i
<QLEN
; i
++) {
341 if(!inQueue(cbuf
, cbuf
->queue
[i
])) {
342 printf("aaagh, corrupted lookahead - in queue[], !inQueue()\n");
343 printf("i=0x%x i1=0x%x i2=0x%x\n",
349 //return initTestLookAhead(cbuf);
353 int initTestLookAhead(comcryptBuf
*cbuf
)
355 #if QUEUE_LOOKAHEAD_BIT
357 unsigned codeWord
= 0;
360 unsigned char *la
= cbuf
->lookAhead
;
362 for(byte
=0; byte
<LOOKAHEAD_SIZE
; byte
++) {
363 for(bit
=1; bit
!=0; bit
<<=1) {
366 * in lookahead, make sure it's in queue[]
371 for(i
=0; i
<QLEN
; i
++) {
372 if(cbuf
->queue
[i
] == codeWord
) {
378 printf("***corrupted init lookahead - in l.a., "
380 printf("codeWord 0x%x\n", codeWord
);
389 #endif /* QUEUE_LOOKAHEAD_BIT */
393 #endif /* COM_LA_DEBUG */
395 void initSigSequence(comcryptBuf
*cbuf
,
396 const unsigned char *key
,
399 unsigned seed
= IN_OFFSET
;
402 for(j
=0; j
<keyLen
; j
++) {
409 cbuf
->sigArray
[0] = (unsigned short)seed
;
414 * Called once per token bit, after processing the token.
416 void nextSigWord(comcryptBuf
*cbuf
,
417 unsigned sigDex
, // same as tokenDex
419 unsigned above
) // jabove, keyabove
422 unsigned short *sigArray
= cbuf
->sigArray
;
426 printf("nextSigWord underflow\n");
429 if(sigDex
> MAX_TOKENS
) {
430 printf("nextSigWord overflow\n");
442 sigArray
[sigDex
] = (sigArray
[sigDex
-1] * (above
+ offset
)) % HASH_PRIME
;
448 * Obfuscate a block of ciphertext.
450 void sigMunge(comcryptBuf
*cbuf
,
451 const unsigned char *tokenPtr
,
453 unsigned char *byteCodePtr
,
454 unsigned char *longCodePtr
)
456 unsigned char tokenBit
= 0x01;
460 for(token
=0; token
<numTokens
; token
++) {
461 sig
= cbuf
->sigArray
[token
];
462 if(*tokenPtr
& tokenBit
) {
463 /* no match - munge longCode - written MSB first */
464 *longCodePtr
++ ^= (unsigned char)(sig
>> 8);
465 *longCodePtr
++ ^= (unsigned char)sig
;
468 /* match - munge byteCode */
469 *byteCodePtr
++ ^= (unsigned char)sig
;
481 * All this can be optimized and tailored to specific platforms, of course...
484 void *ascMalloc(unsigned size
)
494 if(comMallocExt
!= NULL
) {
495 return (comMallocExt
)(size
);
503 h
= NewHandleSys(size
); // system heap is not paged
505 HLockHi(h
); // will move low in system heap
507 if( err
!= errSecSuccess
) break;
510 if( err
!= errSecSuccess
){
520 void ascFree(void *data
)
526 if(comFreeExt
!= NULL
) {
533 h
= RecoverHandle((Ptr
) data
);