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 34unsigned comProfEnable; 35comprof_t cmcTotal; 36comprof_t cmcQueSearch; 37comprof_t cmcQueMatchMove; 38comprof_t cmcQueMissMove; 39comprof_t cmcLevel2; 40comprof_t cmcPerWordOhead; 41 42#endif /*COM_PROFILE*/ 43 44void 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 */ 55comcryptObj 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 */ 114comcryptReturn 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 */ 181void 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 */ 204unsigned 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 */ 305unsigned 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 */ 391static 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 */ 863comcryptReturn 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 */ 933typedef 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 */ 943static 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 1228comcryptReturn 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} 1439