]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_comcryption/lib/comcryption.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_comcryption / lib / comcryption.c
1 /*
2 * Copyright (c) 1997,2011-2012,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 <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "comcryption.h"
29 #include "comDebug.h"
30 #include "comcryptPriv.h"
31
32 #if COM_PROFILE
33
34 unsigned comProfEnable;
35 comprof_t cmcTotal;
36 comprof_t cmcQueSearch;
37 comprof_t cmcQueMatchMove;
38 comprof_t cmcQueMissMove;
39 comprof_t cmcLevel2;
40 comprof_t cmcPerWordOhead;
41
42 #endif /*COM_PROFILE*/
43
44 void comMallocRegister(comMallocExternFcn *mallocExtern,
45 comFreeExternFcn *freeExtern)
46 {
47 comMallocExt = mallocExtern;
48 comFreeExt = freeExtern;
49 }
50
51 /*
52 * Call once at startup. The resulting comcryptObj can be reused multiple
53 * times.
54 */
55 comcryptObj comcryptAlloc(void)
56 {
57 comcryptPriv *cpriv = (comcryptPriv *) ascMalloc(sizeof(comcryptPriv));
58
59 if(cpriv == NULL) {
60 return NULL;
61 }
62 memset(cpriv, 0, sizeof(comcryptPriv));
63
64 #if COMCRYPT_EXPORT_ONLY
65 cpriv->key = (unsigned char *)ascMalloc(EXPORT_KEY_SIZE);
66 #else /*COMCRYPT_EXPORT_ONLY*/
67 cpriv->key = (unsigned char *)ascMalloc(COMCRYPT_MAX_KEYLENGTH);
68 #endif /*COMCRYPT_EXPORT_ONLY*/
69
70 if(cpriv->key == NULL) {
71 return NULL;
72 }
73 cpriv->map = (unsigned char *)ascMalloc(256);
74 cpriv->invmap = (unsigned char *)ascMalloc(256);
75 if((cpriv->map == NULL) || (cpriv->invmap == NULL)) {
76 return NULL;
77 }
78 mallocCodeBufs(&cpriv->cbuf);
79 if((cpriv->cbuf.codeBuf == NULL) ||
80 (cpriv->cbuf.level2Buf == NULL)) {
81 return NULL;
82 }
83 #if QUEUE_LOOKAHEAD
84 if(cpriv->cbuf.lookAhead == NULL) {
85 return NULL;
86 }
87 #endif
88
89 /*
90 * Hard coded limit of two levels of comcryption
91 */
92 cpriv->cbuf.nextBuf = (comcryptBuf *)ascMalloc(sizeof(comcryptBuf));
93 if(cpriv->cbuf.nextBuf == NULL) {
94 return NULL;
95 }
96 mallocCodeBufs(cpriv->cbuf.nextBuf);
97 if((cpriv->cbuf.nextBuf->codeBuf == NULL) ||
98 (cpriv->cbuf.nextBuf->level2Buf == NULL)) {
99 return NULL;
100 }
101 #if QUEUE_LOOKAHEAD
102 if(cpriv->cbuf.nextBuf->lookAhead == NULL) {
103 return NULL;
104 }
105 #endif
106
107 cpriv->cbuf.nextBuf->nextBuf = NULL;
108 return cpriv;
109 }
110
111 /*
112 * Call this before starting every stream process
113 */
114 comcryptReturn comcryptInit(
115 comcryptObj cobj,
116 const unsigned char *key,
117 unsigned keyLen,
118 comcryptOptimize optimize) // CCO_SIZE, etc.
119 {
120 comcryptPriv *cpriv = (comcryptPriv *)cobj;
121 unsigned maxKeySize;
122
123 #if COMCRYPT_EXPORT_ONLY
124 /*
125 * FIXME - NSA might not be satisfied with this, may have to enforce
126 * elsewhere
127 */
128 maxKeySize = EXPORT_KEY_SIZE;
129 #else /*COMCRYPT_EXPORT_ONLY*/
130 maxKeySize = COMCRYPT_MAX_KEYLENGTH;
131 #endif /*COMCRYPT_EXPORT_ONLY*/
132
133 if(keyLen > maxKeySize) {
134 keyLen = maxKeySize;
135 }
136 memmove(cpriv->key, key, keyLen);
137 cpriv->keybytes = keyLen;
138 cpriv->cbuf.codeBufLength = 0;
139 cpriv->cbuf.nextBuf->codeBufLength = 0;
140 cpriv->version = 0;
141 cpriv->versionBytes = 0;
142 cpriv->spareBytes = 0;
143 cpriv->optimize = optimize;
144
145 /*
146 * Derive feature enable bits from optimize arg. This is highly likely
147 * to change....
148 */
149 cpriv->level2enable = 1;
150 cpriv->sigSeqEnable = 1;
151 switch(optimize) {
152 case CCO_TIME:
153 cpriv->level2enable = 0;
154 break;
155 case CCO_TIME_SIZE:
156 cpriv->sigSeqEnable = 0;
157 break;
158 default:
159 break;
160 }
161 #if QUEUE_LOOKAHEAD
162 cpriv->laEnable = 1;
163 #else /* QUEUE_LOOKAHEAD */
164 cpriv->laEnable = 0;
165 #endif /* QUEUE_LOOKAHEAD */
166
167 /*
168 * init queue and maps
169 */
170 initCodeBufs(&cpriv->cbuf, key, keyLen, cpriv->laEnable,
171 cpriv->sigSeqEnable);
172 initCodeBufs(cpriv->cbuf.nextBuf, key, keyLen, cpriv->laEnable,
173 cpriv->sigSeqEnable);
174 key_perm(key, keyLen, cpriv->map, cpriv->invmap);
175 return CCR_SUCCESS;
176 }
177
178 /*
179 * Free a comcryptObj object obtained via comcryptAlloc()
180 */
181 void comcryptObjFree(comcryptObj cobj)
182 {
183 comcryptPriv *cpriv = (comcryptPriv *)cobj;
184
185 if(cpriv->key != NULL) {
186 ascFree(cpriv->key);
187 }
188 if(cpriv->map != NULL) {
189 ascFree(cpriv->map);
190 }
191 if(cpriv->invmap != NULL) {
192 ascFree(cpriv->invmap);
193 }
194 freeCodeBufs(&cpriv->cbuf);
195 ascFree(cpriv);
196 }
197
198 /*
199 * Return the maximum input buffer size allowed for for specified
200 * output buffer size. Note that for both comcrypt and decomcrypt,
201 * to cover the worst case, the output buffer always has to be
202 * larger than the input buffer.
203 */
204 unsigned comcryptMaxInBufSize(comcryptObj cobj,
205 unsigned outBufSize,
206 comcryptOp op)
207 {
208 unsigned fullBlocks;
209 unsigned minCblockSize;
210 unsigned resid;
211 unsigned rtn;
212 unsigned tokenBytes;
213 comcryptPriv *cpriv = (comcryptPriv *)cobj;
214 unsigned ptextFromCodeBuf;
215
216 switch(op) {
217 case CCOP_COMCRYPT:
218 /*
219 * Worst case: no compression. Also, establish a minimum
220 * ciphertext size to accomodate header and one block.
221 */
222 minCblockSize = MIN_CBLOCK_SIZE;
223 if(cpriv->versionBytes == 0) {
224 minCblockSize += CTEXT_HDR_SIZE;
225 }
226 if(outBufSize < (minCblockSize)) {
227 return 0;
228 }
229 if(cpriv->versionBytes == 0) {
230 outBufSize -= CTEXT_HDR_SIZE;
231 }
232 fullBlocks = outBufSize / MAX_CBLOCK_SIZE;
233 rtn = (fullBlocks * CC_BLOCK_SIZE); // bytes of ptext
234
235 /*
236 * code must be even aligned, then chop off one for odd ptext
237 */
238 rtn &= 0xfffffffe;
239 rtn--;
240 if(rtn <= 0) {
241 return 0;
242 }
243 resid = outBufSize % MAX_CBLOCK_SIZE;
244 if(resid) {
245 rtn += resid;
246
247 /*
248 * Account for resid block overhead
249 */
250 if(rtn < MIN_CBLOCK_SIZE) {
251 return 0;
252 }
253 rtn -= MIN_CBLOCK_SIZE;
254
255 tokenBytes = TOKEN_BYTES_FROM_PTEXT(resid);
256 if(rtn <= tokenBytes) {
257 return 0;
258 }
259 rtn -= tokenBytes;
260 }
261 if(rtn > INBUF_TRUNC_THRESH) {
262 /*
263 * Truncate to even block size to minimize partial cipherblocks
264 */
265 rtn &= ~(CC_BLOCK_SIZE - 1);
266 }
267 return rtn;
268
269 case CCOP_DECOMCRYPT:
270 /*
271 * Worst case - 4:1 compression and an almost full block in
272 * codeBuf. Note 4:1 is a super-conservative, easy arithmetic
273 * version of (9/16) squared...
274 */
275 ptextFromCodeBuf = cpriv->cbuf.codeBufLength * 4;
276 if(outBufSize < ptextFromCodeBuf) {
277 /* decrypting codeBuf might overflow output (plaintext)
278 * buffer - won't be able to move anything */
279 rtn = 0;
280 }
281 else {
282 /* can decrypt (this much plainText - ptextFromCodeBuf) / 4 */
283 rtn = (outBufSize - ptextFromCodeBuf) / 4;
284 }
285
286 /* may be able to handle a bit extra for initial decrypt... */
287 if(cpriv->versionBytes < VERSION_BYTES) {
288 rtn += (VERSION_BYTES - cpriv->versionBytes);
289 }
290 if(cpriv->spareBytes < SPARE_BYTES) {
291 rtn += (SPARE_BYTES - cpriv->spareBytes);
292 }
293 return rtn;
294
295 default:
296 ddprintf(("bogus op (%d) in comcryptMaxInBufSize()\n", op));
297 return 0;
298 }
299 }
300
301 /*
302 * Return the maximum output buffer size for specified input buffer size.
303 * Output buffer size will always be larger than input buffer size.
304 */
305 unsigned comcryptMaxOutBufSize(comcryptObj cobj,
306 unsigned inBufSize,
307 comcryptOp op,
308 char final)
309 {
310 unsigned fullBlocks;
311 unsigned resid;
312 unsigned rtn;
313 comcryptPriv *cpriv = (comcryptPriv *)cobj;
314
315 switch(op) {
316 case CCOP_COMCRYPT:
317 fullBlocks = inBufSize / CC_BLOCK_SIZE;
318 rtn = fullBlocks * MAX_CBLOCK_SIZE;
319 resid = inBufSize % CC_BLOCK_SIZE;
320 if(resid != 0) {
321 /*
322 * partial block
323 */
324 unsigned tokenBytes = TOKEN_BYTES_FROM_PTEXT(resid);
325
326 rtn += MIN_CBLOCK_SIZE;
327 rtn += tokenBytes;
328 rtn += resid; // no compression
329 if(resid & 1) {
330 rtn++; // oddByte uses extra
331 }
332 }
333 if((cpriv == NULL) || // i.e., we're being called from mallocCodeBufs
334 (cpriv->versionBytes == 0)) {
335 rtn += CTEXT_HDR_SIZE; // first of a stream
336 }
337 return rtn;
338
339 case CCOP_DECOMCRYPT:
340 /*
341 * Here assume max compression, including resid block in codeBuf
342 */
343 inBufSize += cpriv->cbuf.codeBufLength;
344 if(inBufSize) {
345 /* may be able to handle a bit extra for initial decrypt... */
346 unsigned delta;
347 if(cpriv->versionBytes < VERSION_BYTES) {
348 delta = VERSION_BYTES - cpriv->versionBytes;
349 if(inBufSize > delta) {
350 inBufSize -= delta;
351 }
352 else {
353 inBufSize = 0;
354 }
355 }
356 if(cpriv->spareBytes < SPARE_BYTES) {
357 delta = SPARE_BYTES - cpriv->spareBytes;
358 if(inBufSize > delta) {
359 inBufSize -= delta;
360 }
361 else {
362 inBufSize = 0;
363 }
364 }
365 }
366 rtn = 4 * inBufSize;
367 return rtn;
368
369 default:
370 ddprintf(("bogus op (%d) in comcryptMaxOutBufSize()\n", op));
371 return 0;
372 }
373 }
374
375 /*
376 * Threshold for using memmove() rather than hard-coded loop for
377 * moving queue segment. This was derived empirically on a Pentium;
378 * we should do similar measurements on PPC.
379 */
380 #define QUEUE_MEMMOVE_THRESH 3
381
382 /*
383 * peek at queue[0] before search. This appears to only be a win for
384 * constant plaintext, i.e., the codeword is almost always at queue[0].
385 */
386 #define QUEUE_PEEK 0
387
388 /*
389 * Comcrypt one block.
390 */
391 static comcryptReturn comcryptBlock(
392 comcryptPriv *cpriv,
393 comcryptBuf *cbuf, // not necessarily cpriv->cbuf
394 const unsigned char *plainText,
395 unsigned plainTextLen,
396 unsigned char *cipherText,
397 unsigned *cipherTextLen, // IN/OUT
398 unsigned recursLevel)
399 {
400 unsigned char *byteCodePtr;
401 unsigned char *destByteCodePtr;
402 unsigned char *longCodePtr;
403 unsigned char *startLongCodePtr;
404 unsigned char *tokenPtr;
405 unsigned char *startTokenPtr;
406 unsigned char *startCtextPtr = cipherText;
407 unsigned numTokenBytes; // in bytes, constant
408 unsigned short codeWord;
409 unsigned oddByte = 0;
410 unsigned match;
411 unsigned jmatch=0;
412 unsigned tokenDex = 0; // index into array of token bits
413 unsigned j;
414 unsigned numLongCodes = 0;
415 unsigned numByteCodes = 0;
416 unsigned totalCipherTextLen;
417 unsigned above;
418 unsigned jmatchTotal = 0;
419 unsigned jmatchAvg;
420 comcryptReturn crtn;
421 unsigned char blockDesc = CBD_MAGIC;
422 unsigned fullBlock = 0;
423 int len;
424 queueElt *src;
425 queueElt *dst;
426 queueElt *cbufq = &cbuf->queue[0];
427
428 /*
429 * 'nibble' is added to 'above' in the call to nextSigWord() for
430 * additional security.
431 *
432 * Normal case : nibble = keynybble()
433 * last word on odd byte : nibble = nibbleDex
434 * hit on queue q : nibble = nibbleDex (optimize to avoid keynybble()
435 * call)
436 */
437 unsigned char nibble;
438
439 COMPROF_LOCALS;
440
441 #if COM_LA_DEBUG
442 if(testLookAhead(cbuf, 0, 0)) {
443 return CCR_INTERNAL;
444 }
445 #endif
446
447 laprintf(("comcryptBlock recurs level %d\n", recursLevel));
448
449 /*
450 * Set up ptrs for the three arrays we'll be writing
451 */
452 tokenPtr = cipherText + CTBO_NUM_TOKENS + 1;
453 if(plainTextLen >= (CC_BLOCK_SIZE - 1)) {
454 /*
455 * Optimized for full block - no token count in block. Note
456 * that plainTextLen == (CC_BLOCK_SIZE - 1) is also a full block
457 * in that it uses up a full block's worth of tokens!
458 */
459 numTokenBytes = CC_BLOCK_SIZE >> 4;
460 tokenPtr--;
461 blockDesc |= CBD_FULL_BLOCK;
462 fullBlock = 1;
463 }
464 else {
465 numTokenBytes = (plainTextLen + 15) >> 4;
466 }
467 longCodePtr = tokenPtr + numTokenBytes;
468 startLongCodePtr = longCodePtr;
469 byteCodePtr = cbuf->codeBuf;
470 startTokenPtr = tokenPtr;
471
472 if((unsigned)(longCodePtr - cipherText) > *cipherTextLen) {
473 ddprintf(("comcryptBlock: short block (1)\n"));
474 return CCR_OUTBUFFER_TOO_SMALL;
475 }
476 memset(tokenPtr, 0, numTokenBytes);
477
478 /*
479 * Entering time-critical region. This loop executes once for every
480 * 2 bytes of plaintext. Make every attempt to streamline the code
481 * here; avoid function calls in favor of macros; etc.
482 */
483 while(plainTextLen != 0) {
484
485 /*
486 * assemble a 16-bit word from two bytes if possible
487 */
488 if(plainTextLen == 1) {
489 /*
490 * Odd byte case
491 */
492 codeWord = ((unsigned short)(cpriv->map[*plainText]) << 8) |
493 cpriv->map[0]; // a bit of obfuscation - mapped zero
494 oddByte = 1;
495 blockDesc |= CBD_ODD;
496 plainTextLen--;
497 }
498 else {
499 codeWord = ((unsigned short)(cpriv->map[*plainText]) << 8) |
500 (unsigned short)(cpriv->map[plainText[1]]);
501 plainText += 2;
502 plainTextLen -= 2;
503 }
504
505 /*
506 * Calibrate how much profiling is costing us.
507 */
508 COMPROF_START;
509 COMPROF_END(cmcPerWordOhead);
510
511 /*
512 * See if this word is in queue[]. Skip if oddByte; we'll force
513 * a 16-bit word in that case. Also skip the search if we know
514 * via lookahead that a search would be fruitless.
515 */
516 COMPROF_START; /* cmcQueSearch */
517 match = 0;
518 do { /* while 0 - for easy breaks w/o goto */
519
520 /*
521 * First handle some optimizations and special cases
522 */
523 if(oddByte) {
524 break; // force longcode
525 }
526
527 #if QUEUE_PEEK
528 if(cbufq[0] == codeWord) {
529 match = 1;
530 jmatch = 0;
531 break;
532
533 }
534 #endif /*QUEUE_PEEK*/
535
536 if(cpriv->laEnable && !inQueue(cbuf, codeWord)) {
537 break;
538 }
539
540 /*
541 * OK, do the gruntwork search
542 */
543 for(j=0; j < QLEN; j++) {
544 if(cbufq[j] == codeWord) {
545 match = 1;
546 jmatch = j;
547 break;
548 }
549 }
550
551 #if COM_LA_DEBUG
552 if(cpriv->laEnable && !match) {
553 printf("inQueue, not found in queue!\n");
554 return CCR_INTERNAL;
555 }
556
557 /*
558 * Search for duplicates.
559 */
560 if(match) {
561 for(j=jmatch+1; j<QLEN; j++) {
562 if(cbufq[j] == codeWord) {
563 printf("***Huh! Dup queue entry codeWord 0x%x jmatch "
564 "0x%x 2nd j 0x%x\n",
565 codeWord, jmatch, j);
566 return CCR_INTERNAL;
567 }
568 }
569 }
570 #endif /*COM_LA_DEBUG*/
571 } while(0);
572
573 COMPROF_END(cmcQueSearch);
574
575 /*
576 * Note we measure the overhead on a per-codeword basis. Here,
577 * we ensure that there is exactly one pair of start/end
578 * timestamps per queue move per code word.
579 *
580 * New 17 Dec 1997 - always calculate keynibble for use in signature
581 * sequence update
582 */
583 #if !SKIP_NIBBLE_ON_QUEUE_0
584 nibble = keynybble(cpriv->key, cpriv->keybytes,
585 (cbuf->nybbleDex)++);
586 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
587
588 COMPROF_START;
589 if(match) {
590 /*
591 * 16-bit symbol is in queue. 8 bits of ciphertext, token bit is 0.
592 */
593 if(jmatch == 0) {
594 /*
595 * Optimization: jmatch = 0. Keep state machine in sync,
596 * but skip queue update.
597 */
598 above = 0;
599 laprintf(("...queue hit at queue[0]\n"));
600 #if SKIP_NIBBLE_ON_QUEUE_0
601 nibble = (cbuf->nybbleDex)++;
602 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
603 }
604 else {
605 #if SKIP_NIBBLE_ON_QUEUE_0
606 nibble = keynybble(cpriv->key, cpriv->keybytes,
607 (cbuf->nybbleDex)++);
608 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
609
610 above = (cbuf->f1 * jmatch * (16 + nibble)) >> 9;
611
612 /*
613 * queue[above..(jmatch-1)] move one element towards end
614 * queue[above] = this codeWord
615 */
616 laprintf(("...queue hit, moving 0x%x from 0x%x to 0x%x\n",
617 codeWord, jmatch, above));
618
619 len = (int)jmatch - (int)above;
620 if(len > QUEUE_MEMMOVE_THRESH) {
621 src = &cbufq[above];
622 dst = src + 1;
623 len *= sizeof(queueElt);
624 memmove(dst, src, len);
625 }
626 else {
627 for(j = jmatch; j>above; j--) {
628 cbufq[j] = cbufq[j-1];
629 }
630 }
631
632 cbufq[above] = codeWord;
633 #if COM_LA_DEBUG
634 if(testLookAhead(cbuf, above, jmatch)) {
635 return CCR_INTERNAL;
636 }
637 #endif /*COM_LA_DEBUG*/
638 }
639 COMPROF_END(cmcQueMatchMove);
640
641 codeWord = jmatch;
642 incr1byteFrags(recursLevel);
643 jmatchTotal += jmatch;
644 }
645 else if(oddByte == 0) {
646 /*
647 * 16-bit symbol is not in queue. 16 bits of ciphertext.
648 * Token bit is 1.
649 *
650 * queue[above...QLEN-1] move one element toward end
651 * queue[QLEN-1] discarded
652 * queue[above] = new codeword
653 *
654 * Note we skip this queue manipulation in the oddbyte case, since
655 * we don't really know (or care) if the current code word is in
656 * the queue or not.
657 */
658 #if SKIP_NIBBLE_ON_QUEUE_0
659 nibble = keynybble(cpriv->key, cpriv->keybytes,
660 (cbuf->nybbleDex)++);
661 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
662
663 above = ABOVE(cbuf->f2) + nibble;
664
665 #if COM_DEBUG
666 if(above > QLEN) {
667 printf("Hey Doug! above %d QLEN %d\n", above, QLEN);
668 return CCR_INTERNAL;
669 }
670 #endif
671
672 laprintf(("...queue miss, adding 0x%x at 0x%x, deleting 0x%x\n",
673 codeWord, above, cbufq[QLEN-1]));
674
675 if(cpriv->laEnable) {
676 markInQueue(cbuf, codeWord, 1); // new entry
677 markInQueue(cbuf, cbufq[QLEN-1], 0); // bumped out
678 }
679
680 len = QLEN - 1 - (int)above;
681 if(len > QUEUE_MEMMOVE_THRESH) {
682 src = &cbufq[above];
683 dst = src + 1;
684 len *= sizeof(queueElt);
685 memmove(dst, src, len);
686 }
687 else {
688 for(j=QLEN-1; j > above; j--) {
689 cbufq[j] = cbufq[j-1];
690 }
691 }
692
693 cbufq[above] = codeWord;
694
695 #if COM_LA_DEBUG
696 if(testLookAhead(cbuf, above, 0)) {
697 return CCR_INTERNAL;
698 }
699 #endif /*COM_LA_DEBUG*/
700
701 COMPROF_END(cmcQueMissMove);
702 incr2byteFrags(recursLevel);
703 }
704 else {
705 /*
706 * Odd byte case, at least gather stats.
707 */
708 incr2byteFrags(recursLevel);
709
710 /*
711 * ...and keep this in sync for signature sequence
712 */
713 above = 0;
714 #if SKIP_NIBBLE_ON_QUEUE_0
715 nibble = (cbuf->nybbleDex)++;
716 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
717 }
718
719 updateToken(tokenPtr, tokenDex, !match);
720 tokenDex++;
721
722 if(match) {
723 *byteCodePtr++ = codeWord & 0xff;
724 numByteCodes++;
725 }
726 else {
727 serializeShort(codeWord, longCodePtr);
728 longCodePtr += 2;
729 numLongCodes++;
730 }
731 if(cpriv->sigSeqEnable) {
732 nextSigWord(cbuf, tokenDex, match, (above + nibble));
733 }
734 }
735
736 #if COM_DEBUG
737 if(numTokenBytes != ((tokenDex + 7) >> 3)) {
738 ddprintf(("comcryptBlock: numTokenBytes (%d), tokenDex (%d)\n",
739 numTokenBytes, tokenDex));
740 }
741 #endif /*COM_DEBUG*/
742
743 /*
744 * We already wrote tokens and longcode to cipherText; verify we
745 * didn't overrun
746 */
747 totalCipherTextLen = (unsigned)(longCodePtr - startCtextPtr);
748 if(*cipherTextLen < totalCipherTextLen) {
749 ddprintf(("comcryptBlock: short block (2)\n"));
750 return CCR_OUTBUFFER_TOO_SMALL;
751 }
752 if(!fullBlock) {
753 cipherText[CTBO_NUM_TOKENS] = tokenDex;
754 }
755 cipherText[CTBO_NUM_LONG_CODES] = numLongCodes;
756
757 #if COM_DEBUG
758 if(tokenDex > MAX_TOKENS) {
759 ddprintf(("comcryptBlock: counter overflow!\n"));
760 return CCR_INTERNAL;
761 }
762 if((numByteCodes + numLongCodes) != tokenDex) {
763 ddprintf(("comcryptBlock: counter mismatch!\n"));
764 return CCR_INTERNAL;
765 }
766 #endif /*COM_DEBUG*/
767
768 /*
769 * See if doing a second level comcryption makes sense.
770 */
771 destByteCodePtr = startLongCodePtr + (numLongCodes * 2);
772 if(numByteCodes > 0) {
773 jmatchAvg = jmatchTotal / numByteCodes;
774 }
775 else {
776 jmatchAvg = cbuf->jmatchThresh + 1;
777 }
778 if((recursLevel == 0) && // hard coded recursion limit
779 (cpriv->level2enable) && // enabled by caller
780 (numByteCodes >= cbuf->minByteCode) && // meaningful # of bytecodes
781 (jmatchAvg <= cbuf->jmatchThresh)) { // reasonable compression
782 // already achieved
783
784 unsigned thisCtext = cbuf->level2BufSize;
785
786 COMPROF_START;
787 crtn = comcryptBlock(cpriv,
788 cbuf->nextBuf,
789 cbuf->codeBuf,
790 numByteCodes,
791 cbuf->level2Buf,
792 &thisCtext,
793 recursLevel + 1);
794 if(crtn) {
795 return crtn;
796 }
797
798 /*
799 * Write level2Buf to cipherText (as byteCodeArray).
800 * Size of 2nd level comcrypted byte code follows longcode array,
801 * then the bytecode itself.
802 * First bump totalCipherTextLen by the size of the comcrypted array
803 * plus one (for the size byte itself), and verify no overflow
804 */
805 totalCipherTextLen += (thisCtext + 1);
806 if(*cipherTextLen < totalCipherTextLen) {
807 ddprintf(("comcryptBlock: short block (3)\n"));
808 return CCR_OUTBUFFER_TOO_SMALL;
809 }
810 *destByteCodePtr++ = thisCtext;
811 COMPROF_END(cmcLevel2);
812 memmove(destByteCodePtr, cbuf->level2Buf, thisCtext);
813 blockDesc |= CBD_DOUBLE;
814
815 l2printf(("***2nd-level comcrypt: numByteCodes %d encrypted "
816 "size %d\n", numByteCodes, thisCtext));
817 incrComStat(level2byteCode, numByteCodes);
818 incrComStat(level2cipherText, thisCtext);
819 incrComStat(level2jmatch, jmatchTotal);
820 incrComStat(level2blocks, 1);
821 }
822 else {
823 /*
824 * Normal one-level comcryption. Write byteCodes to ciphertext.
825 * numByteCodes is inferred.
826 */
827 totalCipherTextLen += numByteCodes;
828 if(*cipherTextLen < totalCipherTextLen) {
829 ddprintf(("comcryptBlock: short block (3)\n"));
830 return CCR_OUTBUFFER_TOO_SMALL;
831 }
832 memmove(destByteCodePtr, cbuf->codeBuf, numByteCodes);
833 blockDesc |= CBD_SINGLE;
834 if(recursLevel == 0) {
835 incrComStat(level1blocks, 1);
836 }
837 /* else this is a 2nd-level, our caller will count */
838
839 /*
840 * obfuscate via sigArray (only when we're NOT doing 2nd level
841 * comcrypt)
842 */
843 if(cpriv->sigSeqEnable) {
844 sigMunge(cbuf, startTokenPtr, tokenDex,
845 destByteCodePtr, startLongCodePtr);
846
847 /*
848 * Prime sigArray state machine for next block. Note in the case
849 * of 2nd level, we skip this step, so the next block starts from
850 * the same state as this one did.
851 */
852 cbuf->sigArray[0] = cbuf->sigArray[tokenDex];
853 }
854 }
855 cipherText[CTBO_BLOCK_DESC] = blockDesc;
856 *cipherTextLen = totalCipherTextLen;
857 return CCR_SUCCESS;
858 }
859
860 /*
861 * Main public encrypt function.
862 */
863 comcryptReturn comcryptData(
864 comcryptObj cobj,
865 unsigned char *plainText,
866 unsigned plainTextLen,
867 unsigned char *cipherText, // malloc'd by caller
868 unsigned *cipherTextLen, // IN/OUT
869 comcryptEos endOfStream) // CCE_END_OF_STREAM, etc.
870 {
871 comcryptPriv *cpriv = (comcryptPriv *)cobj;
872 unsigned ctextLen = *cipherTextLen;
873 comcryptReturn crtn;
874 unsigned thisPtext;
875 unsigned thisCtext;
876 COMPROF_LOCALS;
877
878 COMPROF_START;
879 incrComStat(plaintextBytes, plainTextLen);
880 if(cpriv->versionBytes == 0) {
881 /*
882 * First, put header (version, spare) into head of ciphertext.
883 */
884 if(ctextLen < CTEXT_HDR_SIZE) {
885 ddprintf(("comcryptData: overflow (0)\n"));
886 return CCR_OUTBUFFER_TOO_SMALL;
887 }
888 serializeInt(VERSION_3_Dec_97, cipherText);
889 cipherText += VERSION_BYTES;
890 cpriv->versionBytes = VERSION_BYTES;
891 serializeInt(0, cipherText); // spares
892 cipherText += SPARE_BYTES;
893 ctextLen -= CTEXT_HDR_SIZE;
894 }
895
896 /*
897 * OK, grind it out, one block at a time.
898 */
899 while (plainTextLen != 0) {
900 thisPtext = CC_BLOCK_SIZE;
901 if(thisPtext > plainTextLen) {
902 thisPtext = plainTextLen;
903 }
904 thisCtext = ctextLen;
905 crtn = comcryptBlock(cpriv,
906 &cpriv->cbuf,
907 plainText,
908 thisPtext,
909 cipherText,
910 &thisCtext,
911 0); // recurs level
912 if(crtn) {
913 return crtn;
914 }
915 plainText += thisPtext;
916 plainTextLen -= thisPtext;
917 if(thisCtext > ctextLen) {
918 ddprintf(("comcryptData: undetected ciphertext overlow\n"));
919 return CCR_OUTBUFFER_TOO_SMALL;
920 }
921 cipherText += thisCtext;
922 ctextLen -= thisCtext;
923 }
924 *cipherTextLen = *cipherTextLen - ctextLen;
925 incrComStat(ciphertextBytes, *cipherTextLen);
926 COMPROF_END(cmcTotal);
927 return CCR_SUCCESS;
928 }
929
930 /*
931 * Return values from deComcryptBlock().
932 */
933 typedef enum {
934 DCB_SUCCESS, // OK
935 DCB_SHORT, // incomplete block, try again with more ciphertext
936 DCB_PARSE_ERROR, // bad block
937 DCB_OUTBUFFER_TOO_SMALL
938 } dcbReturn;
939
940 /*
941 * Assumes exactly one block of ciphertext, error otherwise.
942 */
943 static dcbReturn deComcryptBlock(
944 comcryptPriv *cpriv,
945 comcryptBuf *cbuf, // not necessarily cpriv->cbuf
946 unsigned char *cipherText,
947 unsigned cipherTextLen,
948 unsigned char *plainText,
949 unsigned *plainTextLen, // IN/OUT
950 comcryptEos endOfStream, // CCE_END_OF_STREAM, etc.
951 unsigned *blockSize) // RETURNED on DCB_SUCCESS
952 {
953 unsigned char *tokenPtr;
954 unsigned numTokenBits; // constant, from ciphertext
955 unsigned numTokenBytes;
956 unsigned char *longCodePtr;
957 unsigned numLongCodes;
958 unsigned char *byteCodePtr;
959 unsigned numByteCodes;
960 unsigned tokenDex;
961 unsigned oddByte = 0;
962 unsigned short codeWord;
963 unsigned char codeByte;
964 unsigned ptextLen = *plainTextLen; // bytes REMAINING
965 unsigned above;
966 unsigned j;
967 unsigned char blockDesc;
968 dcbReturn drtn;
969 int len;
970 queueElt *src;
971 queueElt *dst;
972 int lastWord = 0;
973 queueElt *cbufq = &cbuf->queue[0];
974 int level2 = 0; // 2nd level comcrypted block
975 unsigned match;
976 unsigned char sigSeq; // signature sequence enable
977 unsigned char nibble;
978
979 blockDesc = cipherText[CTBO_BLOCK_DESC];
980 if((blockDesc & CBD_MAGIC_MASK) != CBD_MAGIC) {
981 ddprintf(("deComcryptBlock: bad CBD_MAGIC\n"));
982 return DCB_PARSE_ERROR;
983 }
984
985 /*
986 * Min block size - blockDesc, numLongCodes, numTokens, one token byte,
987 * one bytecode
988 */
989 if(cipherTextLen < 5) {
990 return DCB_SHORT;
991 }
992 if((blockDesc & CBD_FULL_BLOCK_MASK) == CBD_FULL_BLOCK) {
993 /*
994 * # of token bits implied for full block
995 */
996 numTokenBits = TOKEN_BITS_FROM_PTEXT(CC_BLOCK_SIZE);
997 numTokenBytes = TOKEN_BYTES_FROM_PTEXT(CC_BLOCK_SIZE);
998 tokenPtr = cipherText + CTBO_NUM_TOKENS;
999 }
1000 else {
1001 numTokenBits = cipherText[CTBO_NUM_TOKENS];
1002 numTokenBytes = TOKEN_BYTES_FROM_TOKEN_BITS(numTokenBits);
1003 tokenPtr = cipherText + CTBO_NUM_TOKENS + 1;
1004 }
1005 longCodePtr = tokenPtr + numTokenBytes;
1006 numLongCodes = cipherText[CTBO_NUM_LONG_CODES];
1007
1008 byteCodePtr = longCodePtr + (numLongCodes * 2); // may increment...
1009 if((blockDesc & CBD_BLOCK_TYPE_MASK) == CBD_SINGLE) {
1010 /*
1011 * # of bytecodes implied from numTokenBits and numLongCodes
1012 */
1013 numByteCodes = numTokenBits - numLongCodes;
1014 }
1015 else {
1016 /*
1017 * size of 2nd level comcrypted bytecode specified after longCode
1018 * array (and before the bytecode itself).
1019 * Careful, verify that we can read numByteCodes first...
1020 */
1021 if((unsigned)(byteCodePtr - cipherText) > cipherTextLen) {
1022 return DCB_SHORT;
1023 }
1024 numByteCodes = *byteCodePtr++;
1025 level2 = 1;
1026 }
1027 *blockSize = (unsigned)(byteCodePtr - cipherText) + numByteCodes;
1028 if(*blockSize > cipherTextLen) {
1029 return DCB_SHORT;
1030 }
1031
1032 /*
1033 * We now know that we have a complete cipherblock. Go for it.
1034 */
1035 if(level2) {
1036 /*
1037 * this block's bytecode array contains 2nd level comcrypted bytecodes.
1038 */
1039 unsigned thisPtext = cbuf->level2BufSize;
1040 unsigned level1CodeSize;
1041
1042 if(cbuf->nextBuf == NULL) {
1043 ddprintf(("2-level comcypt, no nextBuf available!\n"));
1044 return DCB_PARSE_ERROR;
1045 }
1046 drtn = deComcryptBlock(cpriv,
1047 cbuf->nextBuf,
1048 byteCodePtr,
1049 numByteCodes,
1050 cbuf->level2Buf,
1051 &thisPtext,
1052 CCE_END_OF_STREAM,
1053 &level1CodeSize);
1054 switch(drtn) {
1055 case DCB_SHORT:
1056 ddprintf(("CBT_DOUBLE block, incomplete cipherblock in "
1057 "2nd level code\n"));
1058 return DCB_PARSE_ERROR;
1059
1060 case DCB_OUTBUFFER_TOO_SMALL: // not our fault!
1061 case DCB_PARSE_ERROR:
1062 default:
1063 ddprintf(("2nd-level decomcrypt error (%d)\n", drtn));
1064 return drtn;
1065
1066 case DCB_SUCCESS:
1067 /*
1068 * Supposedly we passed in exactly one cipherblock...
1069 */
1070 if(numByteCodes != level1CodeSize) {
1071 ddprintf(("2nd-level decomcrypt: "
1072 "numByteCodes != level1CodeSize\n"));
1073 return DCB_PARSE_ERROR;
1074 }
1075 l2printf(("2nd-level decomcrypt: ciphertext %d "
1076 "numByteCodes %d\n", numByteCodes, thisPtext));
1077 break;
1078 }
1079 byteCodePtr = cbuf->level2Buf;
1080 numByteCodes = thisPtext;
1081 }
1082
1083 if((blockDesc & CBD_ODD_MASK) == CBD_ODD) {
1084 oddByte = 1;
1085 }
1086
1087 /*
1088 * Skip signature sequence if this was a 2nd level comcrypted block
1089 */
1090 sigSeq = cpriv->sigSeqEnable && !level2;
1091
1092 for(tokenDex=0; tokenDex<numTokenBits; tokenDex++) {
1093 match = !getToken(tokenPtr, tokenDex);
1094
1095 /*
1096 * 17 Dec 1997 - Always calculate this regardless of match
1097 */
1098 nibble = keynybble(cpriv->key, cpriv->keybytes,
1099 (cbuf->nybbleDex)++);
1100
1101 if(match) {
1102 codeByte = *byteCodePtr++;
1103
1104 if(sigSeq) {
1105 codeByte ^= (unsigned char)(cbuf->sigArray[tokenDex]);
1106 }
1107
1108 /*
1109 * dynamically process the queue for match - 8 bits
1110 * of ciphercode, 16 bits of plaintext
1111 */
1112 codeWord = cbufq[codeByte];
1113 above = (cbuf->f1 * codeByte * (16 + nibble)) >> 9;
1114
1115 #if SKIP_NIBBLE_ON_QUEUE_0
1116 if(codeByte == 0) {
1117 /*
1118 * Special case for top of queue optimization during
1119 * comcrypt
1120 */
1121 nibble = cbuf->nybbleDex - 1;
1122 }
1123 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
1124
1125 /*
1126 * queue[above..codeByte] move one element towards end
1127 * queue[above] = this codeWord
1128 */
1129 len = (int)codeByte - (int)above;
1130 if(len > QUEUE_MEMMOVE_THRESH) {
1131 src = &cbufq[above];
1132 dst = src + 1;
1133 len *= sizeof(queueElt);
1134 memmove(dst, src, len);
1135 }
1136 else {
1137 for(j = codeByte; j > above; j--) {
1138 cbufq[j] = cbufq[j-1];
1139 }
1140 }
1141 cbufq[above] = codeWord;
1142 }
1143 else {
1144 /*
1145 * !match, 16 bits of code
1146 */
1147 deserializeShort(codeWord, longCodePtr);
1148 if(sigSeq) {
1149 codeWord ^= cbuf->sigArray[tokenDex];
1150 }
1151
1152 if(oddByte && (tokenDex == (numTokenBits - 1))) {
1153 lastWord = 1;
1154 above = 0;
1155 #if SKIP_NIBBLE_ON_QUEUE_0
1156 nibble = cbuf->nybbleDex - 1;
1157 #endif /*SKIP_NIBBLE_ON_QUEUE_0*/
1158 }
1159 else {
1160 longCodePtr += 2;
1161
1162 /*
1163 * dynamically process the queue for unmatch; skip if this
1164 * is an oddByte codeword.
1165 * queue[above...QLEN-1] move one element toward end
1166 * queue[above] = new codeWord
1167 */
1168 above = ABOVE(cbuf->f2) + nibble;
1169 len = QLEN - 1 - (int)above;
1170 if(len > QUEUE_MEMMOVE_THRESH) {
1171 src = &cbufq[above];
1172 dst = src + 1;
1173 len *= sizeof(queueElt);
1174 memmove(dst, src, len);
1175 }
1176 else {
1177 for(j=QLEN-1; j > above; j--) {
1178 cbufq[j] = cbufq[j-1];
1179 }
1180 }
1181 cbufq[above] = codeWord;
1182 }
1183 }
1184
1185 if(sigSeq) {
1186 /*
1187 * Advance signature sequence state machine.
1188 */
1189 nextSigWord(cbuf, tokenDex+1, match, (above + nibble));
1190 }
1191
1192 /*
1193 * cook up a byte or two of plainText from code word and invmap[]
1194 */
1195 if(ptextLen < 1) {
1196 ddprintf(("decryptBlock: ptext overflow (1)\n"));
1197 return DCB_OUTBUFFER_TOO_SMALL;
1198 }
1199 *plainText++ = cpriv->invmap[(codeWord >> 8) & 0xff];
1200 ptextLen--;
1201 if(lastWord) {
1202 /*
1203 * end of oddByte block.
1204 */
1205 tokenDex++; // for sigArray maintenance
1206 break; // out of main loop
1207 }
1208 else {
1209 if(ptextLen < 1) {
1210 ddprintf(("decryptBlock: ptext overflow (2)\n"));
1211 return DCB_OUTBUFFER_TOO_SMALL;
1212 }
1213 *plainText++ = cpriv->invmap[(codeWord) & 0xff];
1214 ptextLen--;
1215 }
1216 }
1217
1218 /*
1219 * Prime sigArray state machine for next block.
1220 */
1221 if(sigSeq) {
1222 cbuf->sigArray[0] = cbuf->sigArray[tokenDex];
1223 }
1224 *plainTextLen = *plainTextLen - ptextLen;
1225 return DCB_SUCCESS;
1226 }
1227
1228 comcryptReturn deComcryptData(
1229 comcryptObj cobj,
1230 unsigned char *cipherText,
1231 unsigned cipherTextLen,
1232 unsigned char *plainText,
1233 unsigned *plainTextLen, // IN/OUT
1234 comcryptEos endOfStream) // CCE_END_OF_STREAM, etc.
1235
1236 {
1237 comcryptPriv *cpriv = (comcryptPriv *)cobj;
1238 unsigned char *outorigin = plainText;
1239 unsigned ptextLen = *plainTextLen;
1240 unsigned thisPtext; // per block
1241 unsigned blockSize;
1242 dcbReturn drtn;
1243 unsigned ctextUsed;
1244
1245 /*
1246 * Snag version from ciphertext, or as much as we can get
1247 */
1248 while((cpriv->versionBytes < VERSION_BYTES) && cipherTextLen) {
1249 cpriv->version <<= 8;
1250 cpriv->version |= *cipherText;
1251 cpriv->versionBytes++;
1252 cipherText++;
1253 cipherTextLen--;
1254 }
1255
1256 /*
1257 * Then skip over the remainder of the header (currently spares)
1258 */
1259 if((cpriv->spareBytes < SPARE_BYTES) && cipherTextLen) {
1260 unsigned toSkip = SPARE_BYTES - cpriv->spareBytes;
1261
1262 if(toSkip > cipherTextLen) {
1263 toSkip = cipherTextLen;
1264 }
1265 cpriv->spareBytes += toSkip;
1266 cipherText += toSkip;
1267 cipherTextLen -= toSkip;
1268 }
1269
1270 if(cipherTextLen == 0) {
1271 *plainTextLen = 0;
1272 return CCR_SUCCESS;
1273 }
1274
1275 if(cpriv->version != VERSION_3_Dec_97) {
1276 ddprintf(("Incompatible version.\n"));
1277 return CCR_BAD_CIPHERTEXT;
1278 }
1279
1280 while(cipherTextLen != 0) {
1281
1282 /*
1283 * Main loop. First deal with possible existing partial block.
1284 */
1285 if(cpriv->cbuf.codeBufLength != 0) {
1286 unsigned toCopy =
1287 cpriv->cbuf.codeBufSize - cpriv->cbuf.codeBufLength;
1288 unsigned origBufSize = cpriv->cbuf.codeBufLength;
1289
1290 if(toCopy > cipherTextLen) {
1291 toCopy = cipherTextLen;
1292 }
1293 memmove(cpriv->cbuf.codeBuf + cpriv->cbuf.codeBufLength,
1294 cipherText, toCopy);
1295 cpriv->cbuf.codeBufLength += toCopy;
1296
1297 thisPtext = ptextLen;
1298 drtn = deComcryptBlock(cpriv,
1299 &cpriv->cbuf,
1300 cpriv->cbuf.codeBuf,
1301 cpriv->cbuf.codeBufLength,
1302 plainText,
1303 &thisPtext,
1304 endOfStream,
1305 &blockSize);
1306 switch(drtn) {
1307 case DCB_SHORT:
1308 /*
1309 * Incomplete block in codeBuf
1310 */
1311 if(endOfStream == CCE_END_OF_STREAM) {
1312 /*
1313 * Caller thinks this is the end, but we need more
1314 */
1315 ddprintf(("deComcryptData(): CCE_END_OF_STREAM, "
1316 "not end of block\n"));
1317 return CCR_BAD_CIPHERTEXT;
1318 }
1319 cipherTextLen -= toCopy;
1320 if(cipherTextLen != 0) {
1321 /*
1322 * i.e., codeBuf overflow - could be s/w error? Do
1323 * we need a bigger buffer?
1324 */
1325 ddprintf(("deComcryptData: full codeBuf, incomplete "
1326 "block\n"));
1327 return CCR_BAD_CIPHERTEXT;
1328 }
1329 else {
1330 /*
1331 * OK, stash it and try again
1332 */
1333 scprintf(("====incomplete codeBuf, codeBufLength %d, "
1334 "cipherTextLen %d\n",
1335 cpriv->cbuf.codeBufLength, toCopy));
1336 break; // out of main loop (after this switch)
1337 }
1338
1339 case DCB_OUTBUFFER_TOO_SMALL:
1340 ddprintf(("codeBuf decomcrypt error short buf\n"));
1341 return CCR_OUTBUFFER_TOO_SMALL;
1342
1343 case DCB_PARSE_ERROR:
1344 default:
1345 ddprintf(("codeBuf decomcrypt error (%d)\n", drtn));
1346 return CCR_BAD_CIPHERTEXT;
1347
1348 case DCB_SUCCESS:
1349 /*
1350 * ctextUsed is how much of caller's ciphertext we used
1351 * in this buffered block
1352 */
1353 ctextUsed = blockSize - origBufSize;
1354 scprintf(("====decrypted block in codeBuf, blockSize %d, "
1355 "ctextUsed %d, thisPtext %d\n",
1356 blockSize, ctextUsed, thisPtext));
1357 cipherText += ctextUsed;
1358 cipherTextLen -= ctextUsed;
1359 plainText += thisPtext;
1360 ptextLen -= thisPtext;
1361 cpriv->cbuf.codeBufLength = 0;
1362 break;
1363 }
1364
1365 /*
1366 * We might have used up all of caller's cipherText processing
1367 * codeBuf...
1368 */
1369 if(cipherTextLen == 0) {
1370 break; // out of main loop
1371 }
1372
1373 } /* buffered ciphertext in codeBuf */
1374
1375 /*
1376 * Snarf ciphertext, one block at a time.
1377 */
1378
1379 thisPtext = ptextLen;
1380 drtn = deComcryptBlock(cpriv,
1381 &cpriv->cbuf,
1382 cipherText,
1383 cipherTextLen,
1384 plainText,
1385 &thisPtext,
1386 endOfStream,
1387 &blockSize);
1388 switch(drtn) {
1389 case DCB_SHORT:
1390 /*
1391 * Incomplete block
1392 */
1393 if(endOfStream == CCE_END_OF_STREAM) {
1394 ddprintf(("deComcryptData(): CCE_END_OF_STREAM, not end of "
1395 "block (2)\n"));
1396 return CCR_BAD_CIPHERTEXT;
1397 }
1398 if(cipherTextLen >
1399 (cpriv->cbuf.codeBufSize - cpriv->cbuf.codeBufLength)) {
1400 ddprintf(("deComcryptData(): codeBuf overflow!\n"));
1401 return CCR_BAD_CIPHERTEXT;
1402 }
1403 memmove(cpriv->cbuf.codeBuf + cpriv->cbuf.codeBufLength,
1404 cipherText, cipherTextLen);
1405 cpriv->cbuf.codeBufLength += cipherTextLen;
1406 cipherTextLen = 0;
1407 scprintf(("====Incomplete block, cipherTextLen %d "
1408 "codeBufLength %d\n", cipherTextLen,
1409 cpriv->cbuf.codeBufLength));
1410 break; // actually out of main loop
1411
1412 case DCB_PARSE_ERROR:
1413 case DCB_OUTBUFFER_TOO_SMALL:
1414 default:
1415 return CCR_BAD_CIPHERTEXT;
1416
1417 case DCB_SUCCESS:
1418 if(ptextLen < thisPtext) {
1419 /*
1420 * Software error
1421 */
1422 ddprintf(("deComcryptData: undetected ptext "
1423 "overflow (2)\n"));
1424 return CCR_BAD_CIPHERTEXT;
1425 }
1426 plainText += thisPtext;
1427 ptextLen -= thisPtext;
1428 cipherText += blockSize;
1429 cipherTextLen -= blockSize;
1430 scprintf(("====decrypted one block, blockSize %d "
1431 "thisPtext %d\n", blockSize, thisPtext));
1432 break;
1433 }
1434 } /* main loop */
1435
1436 *plainTextLen = (unsigned)(plainText - outorigin);
1437 return CCR_SUCCESS;
1438 }