]> git.saurik.com Git - apple/security.git/blame_incremental - libsecurity_comcryption/lib/comcryptPriv.c
Security-55471.14.18.tar.gz
[apple/security.git] / libsecurity_comcryption / lib / comcryptPriv.c
... / ...
CommitLineData
1/*
2 File: comcryptPriv.c
3
4 Contains: private routines 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/23/97 dpm Added keyHash(), used result to initialize
14 nybbleDex and queue.
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
18
19 To Do:
20*/
21
22#include "comcryptPriv.h"
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#ifdef macintosh
27#include <MacMemory.h>
28#endif
29
30/* if NULL, use our own */
31comMallocExternFcn *comMallocExt = NULL;
32comFreeExternFcn *comFreeExt = NULL;
33
34#if COM_STATS
35comStats _comStats;
36
37void resetComStats()
38{
39 memset(&_comStats, 0, sizeof(comStats));
40}
41
42void getComStats(comStats *stats)
43{
44 *stats = _comStats;
45}
46
47#else /*COM_STATS*/
48
49#define incrComStat(stat, num)
50
51#endif /*COM_STATS*/
52
53/*
54 * Generate a symbol permutation from the key.
55 */
56void key_perm(
57 const unsigned char *key,
58 int keybytes,
59 unsigned char *map,
60 unsigned char *invmap)
61{
62 int i, j, tmp, sum;
63
64 for(sum = 0, j = 0; j < keybytes; j++) {
65 sum += key[j];
66 }
67 for(j=0; j < 256; j++) {
68 map[j] = j;
69 }
70 for(j=0; j < 255; j++) {
71 i = (key[j % keybytes] + j*sum) & 0xff;
72 tmp = map[i];
73 map[i] = map[j];
74 map[j] = tmp;
75 }
76 for(j=0; j<256; j++) {
77 invmap[map[j]] = j;
78 }
79}
80
81int keybyte(
82 const unsigned char *key,
83 int keybytes,
84 int index)
85{
86 return((int) key[index % keybytes]);
87}
88
89int keynybble(
90 const unsigned char *key,
91 int keybytes,
92 int index)
93{
94 int i = index % (2*keybytes);
95 int j;
96
97 j = key[i>>1]; /* Which byte. */
98 if(i & 1) j >>= 4; /* Which nybble. */
99 return(j & 0xf);
100}
101
102/*
103 * Hash a key array.
104 */
105
106#define HASH_SEED 3
107#define HASH_REDUCE 1023
108
109static unsigned keyHash(const unsigned char *key, unsigned keylen)
110{
111 unsigned x = HASH_SEED; /* Any seed in [1,p-1]. Like SEED = 3. */
112 unsigned ctr;
113
114 for(ctr=0; ctr<keylen; ctr++) {
115 x = (x * (key[ctr] + (ctr & HASH_REDUCE) + 1)) % HASH_PRIME;
116 }
117 return x;
118}
119
120void mallocCodeBufs(comcryptBuf *cbuf)
121{
122 /*
123 * calculate required buffer sizes.
124 *
125 * Assume max required codeBuf size is the max size of ciphertext needed
126 * to decrypt one block of plaintext.
127 */
128 cbuf->codeBufSize = comcryptMaxOutBufSize(NULL,
129 CC_BLOCK_SIZE,
130 CCOP_COMCRYPT,
131 1);
132 cbuf->codeBuf = (unsigned char *)ascMalloc(cbuf->codeBufSize);
133
134 /*
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.
137 */
138 cbuf->level2BufSize = comcryptMaxOutBufSize(NULL,
139 MAX_TOKENS, // one byte per token
140 CCOP_COMCRYPT,
141 1);
142 cbuf->level2Buf = (unsigned char *)ascMalloc(cbuf->level2BufSize);
143
144 cbuf->queue = (queueElt *)ascMalloc(sizeof(queueElt) * QLEN);
145
146 #if QUEUE_LOOKAHEAD
147 /*
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).
151 *
152 * FIXME : should do the malloc of lookAhead buffer lazily for
153 * non-Mac platforms.
154 */
155 cbuf->lookAhead = (unsigned char *)ascMalloc(LOOKAHEAD_SIZE);
156 #else /* QUEUE_LOOKAHEAD */
157 cbuf->lookAhead = NULL;
158 #endif /* QUEUE_LOOKAHEAD */
159
160 /*
161 * This maybe should also be done dynamically, lazily...
162 */
163 cbuf->sigArray = (unsigned *)ascMalloc((MAX_TOKENS + 1) * sizeof(unsigned));
164}
165
166void initCodeBufs(
167 comcryptBuf *cbuf,
168 const unsigned char *key,
169 unsigned keyLen,
170 unsigned char laEnable,
171 unsigned char sigSeqEnable)
172{
173 unsigned ct;
174 unsigned qval;
175 unsigned char khash = (unsigned char)keyHash(key, keyLen);
176
177 cbuf->nybbleDex = khash;
178
179 if(laEnable) {
180 memset(cbuf->lookAhead, 0, LOOKAHEAD_SIZE);
181 }
182
183 laprintf(("initing queue and lookahead\n"));
184
185 for(ct=0; ct<QLEN; ct++) {
186 /*
187 * New queue init 23 Dec - init from khash
188 */
189 unsigned short sbyte = ct ^ khash;
190 qval = (sbyte << 8) | ct;
191 cbuf->queue[ct] = qval;
192 if(laEnable) {
193 markInQueue(cbuf, qval, 1);
194 }
195 }
196 // note cbuf->nybbleDex = khash on return...
197
198 cbuf->f1 = F1_DEFAULT;
199 cbuf->f2 = F2_DEFAULT;
200 cbuf->jmatchThresh = THRESH_2LEVEL_JMATCH_DEF;
201 cbuf->minByteCode = THRESH_2LEVEL_NUMBYTECODES_DEF;
202 if(sigSeqEnable) {
203 initSigSequence(cbuf, key, keyLen);
204 }
205}
206
207void freeCodeBufs(comcryptBuf *cbuf)
208{
209 if(cbuf->queue != NULL) {
210 ascFree(cbuf->queue);
211 }
212 if(cbuf->codeBuf != NULL) {
213 ascFree(cbuf->codeBuf);
214 }
215 if(cbuf->level2Buf != NULL) {
216 ascFree(cbuf->level2Buf);
217 }
218 if(cbuf->nextBuf != NULL) {
219 freeCodeBufs(cbuf->nextBuf);
220 ascFree(cbuf->nextBuf);
221 cbuf->nextBuf = NULL;
222 }
223 if(cbuf->lookAhead != NULL) {
224 ascFree(cbuf->lookAhead);
225 }
226 if(cbuf->sigArray != NULL) {
227 ascFree(cbuf->sigArray);
228 }
229}
230
231void serializeInt(
232 unsigned i,
233 unsigned char *buf)
234{
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);
239}
240
241unsigned deserializeInt(unsigned char *buf)
242{
243 unsigned i;
244
245 i = ((unsigned)buf[0]) << 24;
246 i |= ((unsigned)buf[1]) << 16;
247 i |= ((unsigned)buf[2]) << 8;
248 i |= buf[3];
249 return i;
250}
251
252#if COM_PARAM_ENABLE
253
254unsigned getF1(comcryptObj cobj)
255{
256 comcryptPriv *cpriv = (comcryptPriv *)cobj;
257
258 return cpriv->cbuf.f1;
259}
260
261void setF1(comcryptObj cobj, unsigned f1)
262{
263 comcryptPriv *cpriv = (comcryptPriv *)cobj;
264
265 cpriv->cbuf.f1 = f1;
266 if(cpriv->cbuf.nextBuf != NULL) {
267 cpriv->cbuf.nextBuf->f1 = f1;
268 }
269}
270
271unsigned getF2(comcryptObj cobj)
272{
273 comcryptPriv *cpriv = (comcryptPriv *)cobj;
274
275 return cpriv->cbuf.f2;
276}
277
278void setF2(comcryptObj cobj, unsigned f2)
279{
280 comcryptPriv *cpriv = (comcryptPriv *)cobj;
281
282 cpriv->cbuf.f2 = f2;
283 if(cpriv->cbuf.nextBuf != NULL) {
284 cpriv->cbuf.nextBuf->f2 = f2;
285 }
286}
287
288unsigned getJmatchThresh(comcryptObj cobj)
289{
290 comcryptPriv *cpriv = (comcryptPriv *)cobj;
291
292 return cpriv->cbuf.jmatchThresh;
293}
294
295void setJmatchThresh(comcryptObj cobj, unsigned jmatchThresh)
296{
297 comcryptPriv *cpriv = (comcryptPriv *)cobj;
298
299 cpriv->cbuf.jmatchThresh = jmatchThresh;
300 if(cpriv->cbuf.nextBuf != NULL) {
301 cpriv->cbuf.nextBuf->jmatchThresh = jmatchThresh;
302 }
303}
304
305unsigned getMinByteCode(comcryptObj cobj)
306{
307 comcryptPriv *cpriv = (comcryptPriv *)cobj;
308
309 return cpriv->cbuf.minByteCode;
310}
311
312void setMinByteCode(comcryptObj cobj, unsigned minByteCode)
313{
314 comcryptPriv *cpriv = (comcryptPriv *)cobj;
315
316 cpriv->cbuf.minByteCode = minByteCode;
317 if(cpriv->cbuf.nextBuf != NULL) {
318 cpriv->cbuf.nextBuf->minByteCode = minByteCode;
319 }
320}
321
322#endif /*COM_PARAM_ENABLE*/
323
324
325#if COM_LA_DEBUG
326
327/*
328 * Verify integrity of lookahead w.r.t. queue.
329 */
330int testLookAhead(comcryptBuf *cbuf, int i1, int i2)
331{
332 unsigned i;
333
334 if(!cbuf->laEnable) {
335 return 0;
336 }
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",
341 i, i1, i2);
342 printf("\n");
343 exit(1);
344 }
345 }
346 //return initTestLookAhead(cbuf);
347 return 0;
348}
349
350int initTestLookAhead(comcryptBuf *cbuf)
351{
352 #if QUEUE_LOOKAHEAD_BIT
353
354 unsigned codeWord = 0;
355 unsigned char bit;
356 unsigned short byte;
357 unsigned char *la = cbuf->lookAhead;
358
359 for(byte=0; byte<LOOKAHEAD_SIZE; byte++) {
360 for(bit=1; bit!=0; bit<<=1) {
361 if(la[byte] & bit) {
362 /*
363 * in lookahead, make sure it's in queue[]
364 */
365 int i;
366 int found = 0;
367
368 for(i=0; i<QLEN; i++) {
369 if(cbuf->queue[i] == codeWord) {
370 found = 1;
371 break;
372 }
373 }
374 if(!found) {
375 printf("***corrupted init lookahead - in l.a., "
376 "not in queue[]\n");
377 printf("codeWord 0x%x\n", codeWord);
378 printf("\n");
379 exit(1);
380 }
381 }
382 codeWord++;
383 }
384 }
385
386 #endif /* QUEUE_LOOKAHEAD_BIT */
387 return 0;
388}
389
390#endif /* COM_LA_DEBUG */
391
392void initSigSequence(comcryptBuf *cbuf,
393 const unsigned char *key,
394 unsigned keyLen)
395{
396 unsigned seed = IN_OFFSET;
397 unsigned j;
398
399 for(j=0; j<keyLen; j++) {
400 seed += key[j];
401 }
402 seed %= HASH_PRIME;
403 if(seed == 0) {
404 seed = IN_OFFSET;
405 }
406 cbuf->sigArray[0] = (unsigned short)seed;
407}
408
409#if 0
410/*
411 * Called once per token bit, after processing the token.
412 */
413void nextSigWord(comcryptBuf *cbuf,
414 unsigned sigDex, // same as tokenDex
415 unsigned match,
416 unsigned above) // jabove, keyabove
417{
418 unsigned offset;
419 unsigned short *sigArray = cbuf->sigArray;
420
421 #if COM_DEBUG
422 if(sigDex == 0) {
423 printf("nextSigWord underflow\n");
424 exit(1);
425 }
426 if(sigDex > MAX_TOKENS) {
427 printf("nextSigWord overflow\n");
428 exit(1);
429 }
430 #endif
431
432 if(match) {
433 offset = IN_OFFSET;
434 }
435 else {
436 offset = OUT_OFFSET;
437 }
438#if 1
439 sigArray[sigDex] = (sigArray[sigDex-1] * (above + offset)) % HASH_PRIME;
440#endif
441}
442#endif
443
444/*
445 * Obfuscate a block of ciphertext.
446 */
447void sigMunge(comcryptBuf *cbuf,
448 const unsigned char *tokenPtr,
449 unsigned numTokens,
450 unsigned char *byteCodePtr,
451 unsigned char *longCodePtr)
452{
453 unsigned char tokenBit = 0x01;
454 unsigned token;
455 unsigned short sig;
456
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;
463 }
464 else {
465 /* match - munge byteCode */
466 *byteCodePtr++ ^= (unsigned char)sig;
467 }
468 tokenBit <<= 1;
469 if(tokenBit == 0) {
470 tokenBit = 0x01;
471 tokenPtr++;
472 }
473 }
474}
475
476
477/*
478 * All this can be optimized and tailored to specific platforms, of course...
479 */
480
481void *ascMalloc(unsigned size)
482{
483 #ifdef macintosh
484
485 Handle h;
486 OSErr err;
487 Ptr p;
488
489 #endif /* mac */
490
491 if(comMallocExt != NULL) {
492 return (comMallocExt)(size);
493 }
494
495 #ifdef macintosh
496
497 h = nil;
498 err = errSecSuccess;
499
500 h = NewHandleSys(size); // system heap is not paged
501 do{
502 HLockHi(h); // will move low in system heap
503 err = MemError();
504 if( err != errSecSuccess ) break;
505 p = *h;
506 }while(0);
507 if( err != errSecSuccess ){
508 return NULL;
509 }
510 return p;
511
512 #else /* others...*/
513 return malloc(size);
514 #endif
515}
516
517void ascFree(void *data)
518{
519 #ifdef macintosh
520 Handle h;
521 #endif
522
523 if(comFreeExt != NULL) {
524 (comFreeExt)(data);
525 return;
526 }
527
528 #ifdef macintosh
529 if( data != nil ){
530 h = RecoverHandle((Ptr) data);
531 DisposeHandle(h);
532 }
533
534 #else /* others */
535 free(data);
536 #endif
537}