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