|
|
1.1 root 1: /* 1.1.1.8 ! root 2: Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved. 1.1 root 3: 1.1.1.8 ! root 4: Governed by the TrueCrypt License 3.0 the full text of which is contained in 1.1.1.7 root 5: the file License.txt included in TrueCrypt binary and source code distribution 6: packages. 1.1 root 7: */ 8: 1.1.1.3 root 9: /* If native 64-bit data types are not available, define TC_NO_COMPILER_INT64. 1.1 root 10: 1.1.1.3 root 11: For big-endian platforms define BYTE_ORDER as BIG_ENDIAN. */ 1.1 root 12: 13: 14: #ifdef TC_MINIMIZE_CODE_SIZE 1.1.1.3 root 15: // Preboot/boot version 16: # ifndef TC_NO_COMPILER_INT64 17: # define TC_NO_COMPILER_INT64 1.1 root 18: # endif 1.1.1.3 root 19: # pragma optimize ("tl", on) 1.1 root 20: #endif 21: 1.1.1.6 root 22: #ifdef TC_NO_COMPILER_INT64 23: # include <memory.h> 24: #endif 1.1 root 25: 26: #include "Xts.h" 27: 28: 1.1.1.3 root 29: #ifndef TC_NO_COMPILER_INT64 1.1 root 30: 31: // length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size 32: // ks: the primary key schedule 33: // ks2: the secondary key schedule 34: // startDataUnitNo: The sequential number of the data unit with which the buffer starts. 35: // startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo. 36: // When encrypting the data unit from its first block, startCipherBlockNo is 0. 37: // The startCipherBlockNo value applies only to the first data unit in the buffer; each successive 38: // data unit is encrypted from its first block. The start of the buffer does not have to be 39: // aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it 40: // is not aligned, startCipherBlockNo must reflect the misalignment accordingly. 41: void EncryptBufferXTS (unsigned __int8 *buffer, 42: TC_LARGEST_COMPILER_UINT length, 43: const UINT64_STRUCT *startDataUnitNo, 44: unsigned int startCipherBlockNo, 45: unsigned __int8 *ks, 46: unsigned __int8 *ks2, 47: int cipher) 48: { 1.1.1.8 ! root 49: if (CipherSupportsIntraDataUnitParallelization (cipher)) ! 50: EncryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher); ! 51: else ! 52: EncryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher); ! 53: } ! 54: ! 55: ! 56: // Optimized for encryption algorithms supporting intra-data-unit parallelization ! 57: static void EncryptBufferXTSParallel (unsigned __int8 *buffer, ! 58: TC_LARGEST_COMPILER_UINT length, ! 59: const UINT64_STRUCT *startDataUnitNo, ! 60: unsigned int startCipherBlockNo, ! 61: unsigned __int8 *ks, ! 62: unsigned __int8 *ks2, ! 63: int cipher) ! 64: { ! 65: unsigned __int8 finalCarry; ! 66: unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE]; ! 67: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; ! 68: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; ! 69: unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues; ! 70: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; ! 71: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; ! 72: unsigned __int64 *dataUnitBufPtr; ! 73: unsigned int startBlock = startCipherBlockNo, endBlock, block; ! 74: unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1; ! 75: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; ! 76: ! 77: /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the ! 78: finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block ! 79: number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented ! 80: as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if ! 81: the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is ! 82: derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ ! 83: ! 84: // Convert the 64-bit data unit number into a little-endian 16-byte array. ! 85: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. ! 86: dataUnitNo = startDataUnitNo->Value; ! 87: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); ! 88: *((unsigned __int64 *) byteBufUnitNo + 1) = 0; ! 89: ! 90: if (length % BYTES_PER_XTS_BLOCK) ! 91: TC_THROW_FATAL_EXCEPTION; ! 92: ! 93: blockCount = length / BYTES_PER_XTS_BLOCK; ! 94: ! 95: // Process all blocks in the buffer ! 96: while (blockCount > 0) ! 97: { ! 98: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) ! 99: endBlock = startBlock + (unsigned int) blockCount; ! 100: else ! 101: endBlock = BLOCKS_PER_XTS_DATA_UNIT; ! 102: ! 103: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 104: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; ! 105: ! 106: // Encrypt the data unit number using the secondary key (in order to generate the first ! 107: // whitening value for this data unit) ! 108: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); ! 109: *(whiteningValuePtr64 + 1) = 0; ! 110: EncipherBlock (cipher, whiteningValue, ks2); ! 111: ! 112: // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit ! 113: // whitening values are stored in memory as a sequence of 64-bit integers in reverse order. ! 114: for (block = 0; block < endBlock; block++) ! 115: { ! 116: if (block >= startBlock) ! 117: { ! 118: *whiteningValuesPtr64-- = *whiteningValuePtr64++; ! 119: *whiteningValuesPtr64-- = *whiteningValuePtr64; ! 120: } ! 121: else ! 122: whiteningValuePtr64++; ! 123: ! 124: // Derive the next whitening value ! 125: ! 126: #if BYTE_ORDER == LITTLE_ENDIAN ! 127: ! 128: // Little-endian platforms ! 129: ! 130: finalCarry = ! 131: (*whiteningValuePtr64 & 0x8000000000000000) ? ! 132: 135 : 0; ! 133: ! 134: *whiteningValuePtr64-- <<= 1; ! 135: ! 136: if (*whiteningValuePtr64 & 0x8000000000000000) ! 137: *(whiteningValuePtr64 + 1) |= 1; ! 138: ! 139: *whiteningValuePtr64 <<= 1; ! 140: #else ! 141: ! 142: // Big-endian platforms ! 143: ! 144: finalCarry = ! 145: (*whiteningValuePtr64 & 0x80) ? ! 146: 135 : 0; ! 147: ! 148: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); ! 149: ! 150: whiteningValuePtr64--; ! 151: ! 152: if (*whiteningValuePtr64 & 0x80) ! 153: *(whiteningValuePtr64 + 1) |= 0x0100000000000000; ! 154: ! 155: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); ! 156: #endif ! 157: ! 158: whiteningValue[0] ^= finalCarry; ! 159: } ! 160: ! 161: dataUnitBufPtr = bufPtr; ! 162: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 163: ! 164: // Encrypt all blocks in this data unit ! 165: ! 166: for (block = startBlock; block < endBlock; block++) ! 167: { ! 168: // Pre-whitening ! 169: *bufPtr++ ^= *whiteningValuesPtr64--; ! 170: *bufPtr++ ^= *whiteningValuesPtr64--; ! 171: } ! 172: ! 173: // Actual encryption ! 174: EncipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock); ! 175: ! 176: bufPtr = dataUnitBufPtr; ! 177: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 178: ! 179: for (block = startBlock; block < endBlock; block++) ! 180: { ! 181: // Post-whitening ! 182: *bufPtr++ ^= *whiteningValuesPtr64--; ! 183: *bufPtr++ ^= *whiteningValuesPtr64--; ! 184: } ! 185: ! 186: blockCount -= endBlock - startBlock; ! 187: startBlock = 0; ! 188: dataUnitNo++; ! 189: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); ! 190: } ! 191: ! 192: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); ! 193: FAST_ERASE64 (whiteningValues, sizeof (whiteningValues)); ! 194: } ! 195: ! 196: ! 197: // Optimized for encryption algorithms not supporting intra-data-unit parallelization ! 198: static void EncryptBufferXTSNonParallel (unsigned __int8 *buffer, ! 199: TC_LARGEST_COMPILER_UINT length, ! 200: const UINT64_STRUCT *startDataUnitNo, ! 201: unsigned int startCipherBlockNo, ! 202: unsigned __int8 *ks, ! 203: unsigned __int8 *ks2, ! 204: int cipher) ! 205: { 1.1 root 206: unsigned __int8 finalCarry; 207: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; 208: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; 209: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; 210: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; 211: unsigned int startBlock = startCipherBlockNo, endBlock, block; 212: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; 213: 214: /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the 215: finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block 216: number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented 217: as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if 218: the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is 219: derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ 220: 221: // Convert the 64-bit data unit number into a little-endian 16-byte array. 222: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. 223: dataUnitNo = startDataUnitNo->Value; 224: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); 225: *((unsigned __int64 *) byteBufUnitNo + 1) = 0; 226: 227: if (length % BYTES_PER_XTS_BLOCK) 228: TC_THROW_FATAL_EXCEPTION; 229: 230: blockCount = length / BYTES_PER_XTS_BLOCK; 231: 232: // Process all blocks in the buffer 233: while (blockCount > 0) 234: { 235: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) 236: endBlock = startBlock + (unsigned int) blockCount; 237: else 238: endBlock = BLOCKS_PER_XTS_DATA_UNIT; 239: 240: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; 241: 242: // Encrypt the data unit number using the secondary key (in order to generate the first 243: // whitening value for this data unit) 244: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); 245: *(whiteningValuePtr64 + 1) = 0; 246: EncipherBlock (cipher, whiteningValue, ks2); 247: 1.1.1.3 root 248: // Generate (and apply) subsequent whitening values for blocks in this data unit and 249: // encrypt all relevant blocks in this data unit 1.1 root 250: for (block = 0; block < endBlock; block++) 251: { 252: if (block >= startBlock) 253: { 1.1.1.3 root 254: // Pre-whitening 255: *bufPtr++ ^= *whiteningValuePtr64++; 256: *bufPtr-- ^= *whiteningValuePtr64--; 257: 258: // Actual encryption 259: EncipherBlock (cipher, bufPtr, ks); 260: 261: // Post-whitening 262: *bufPtr++ ^= *whiteningValuePtr64++; 263: *bufPtr++ ^= *whiteningValuePtr64; 1.1 root 264: } 265: else 266: whiteningValuePtr64++; 267: 268: // Derive the next whitening value 269: 270: #if BYTE_ORDER == LITTLE_ENDIAN 271: 1.1.1.3 root 272: // Little-endian platforms 1.1 root 273: 274: finalCarry = 275: (*whiteningValuePtr64 & 0x8000000000000000) ? 276: 135 : 0; 277: 278: *whiteningValuePtr64-- <<= 1; 279: 280: if (*whiteningValuePtr64 & 0x8000000000000000) 281: *(whiteningValuePtr64 + 1) |= 1; 282: 283: *whiteningValuePtr64 <<= 1; 284: #else 1.1.1.3 root 285: 286: // Big-endian platforms 1.1 root 287: 288: finalCarry = 289: (*whiteningValuePtr64 & 0x80) ? 290: 135 : 0; 291: 292: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); 293: 294: whiteningValuePtr64--; 295: 296: if (*whiteningValuePtr64 & 0x80) 297: *(whiteningValuePtr64 + 1) |= 0x0100000000000000; 298: 299: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); 300: #endif 301: 302: whiteningValue[0] ^= finalCarry; 303: } 304: 1.1.1.3 root 305: blockCount -= endBlock - startBlock; 1.1 root 306: startBlock = 0; 307: dataUnitNo++; 308: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); 309: } 310: 1.1.1.3 root 311: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); 1.1 root 312: } 313: 314: 315: // For descriptions of the input parameters, see EncryptBufferXTS(). 316: void DecryptBufferXTS (unsigned __int8 *buffer, 317: TC_LARGEST_COMPILER_UINT length, 318: const UINT64_STRUCT *startDataUnitNo, 319: unsigned int startCipherBlockNo, 320: unsigned __int8 *ks, 321: unsigned __int8 *ks2, 322: int cipher) 323: { 1.1.1.8 ! root 324: if (CipherSupportsIntraDataUnitParallelization (cipher)) ! 325: DecryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher); ! 326: else ! 327: DecryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher); ! 328: } ! 329: ! 330: ! 331: // Optimized for encryption algorithms supporting intra-data-unit parallelization ! 332: static void DecryptBufferXTSParallel (unsigned __int8 *buffer, ! 333: TC_LARGEST_COMPILER_UINT length, ! 334: const UINT64_STRUCT *startDataUnitNo, ! 335: unsigned int startCipherBlockNo, ! 336: unsigned __int8 *ks, ! 337: unsigned __int8 *ks2, ! 338: int cipher) ! 339: { ! 340: unsigned __int8 finalCarry; ! 341: unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE]; ! 342: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; ! 343: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; ! 344: unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues; ! 345: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; ! 346: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; ! 347: unsigned __int64 *dataUnitBufPtr; ! 348: unsigned int startBlock = startCipherBlockNo, endBlock, block; ! 349: unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1; ! 350: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; ! 351: ! 352: // Convert the 64-bit data unit number into a little-endian 16-byte array. ! 353: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. ! 354: dataUnitNo = startDataUnitNo->Value; ! 355: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); ! 356: *((unsigned __int64 *) byteBufUnitNo + 1) = 0; ! 357: ! 358: if (length % BYTES_PER_XTS_BLOCK) ! 359: TC_THROW_FATAL_EXCEPTION; ! 360: ! 361: blockCount = length / BYTES_PER_XTS_BLOCK; ! 362: ! 363: // Process all blocks in the buffer ! 364: while (blockCount > 0) ! 365: { ! 366: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) ! 367: endBlock = startBlock + (unsigned int) blockCount; ! 368: else ! 369: endBlock = BLOCKS_PER_XTS_DATA_UNIT; ! 370: ! 371: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 372: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; ! 373: ! 374: // Encrypt the data unit number using the secondary key (in order to generate the first ! 375: // whitening value for this data unit) ! 376: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); ! 377: *(whiteningValuePtr64 + 1) = 0; ! 378: EncipherBlock (cipher, whiteningValue, ks2); ! 379: ! 380: // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit ! 381: // whitening values are stored in memory as a sequence of 64-bit integers in reverse order. ! 382: for (block = 0; block < endBlock; block++) ! 383: { ! 384: if (block >= startBlock) ! 385: { ! 386: *whiteningValuesPtr64-- = *whiteningValuePtr64++; ! 387: *whiteningValuesPtr64-- = *whiteningValuePtr64; ! 388: } ! 389: else ! 390: whiteningValuePtr64++; ! 391: ! 392: // Derive the next whitening value ! 393: ! 394: #if BYTE_ORDER == LITTLE_ENDIAN ! 395: ! 396: // Little-endian platforms ! 397: ! 398: finalCarry = ! 399: (*whiteningValuePtr64 & 0x8000000000000000) ? ! 400: 135 : 0; ! 401: ! 402: *whiteningValuePtr64-- <<= 1; ! 403: ! 404: if (*whiteningValuePtr64 & 0x8000000000000000) ! 405: *(whiteningValuePtr64 + 1) |= 1; ! 406: ! 407: *whiteningValuePtr64 <<= 1; ! 408: ! 409: #else ! 410: // Big-endian platforms ! 411: ! 412: finalCarry = ! 413: (*whiteningValuePtr64 & 0x80) ? ! 414: 135 : 0; ! 415: ! 416: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); ! 417: ! 418: whiteningValuePtr64--; ! 419: ! 420: if (*whiteningValuePtr64 & 0x80) ! 421: *(whiteningValuePtr64 + 1) |= 0x0100000000000000; ! 422: ! 423: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); ! 424: #endif ! 425: ! 426: whiteningValue[0] ^= finalCarry; ! 427: } ! 428: ! 429: dataUnitBufPtr = bufPtr; ! 430: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 431: ! 432: // Decrypt blocks in this data unit ! 433: ! 434: for (block = startBlock; block < endBlock; block++) ! 435: { ! 436: *bufPtr++ ^= *whiteningValuesPtr64--; ! 437: *bufPtr++ ^= *whiteningValuesPtr64--; ! 438: } ! 439: ! 440: DecipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock); ! 441: ! 442: bufPtr = dataUnitBufPtr; ! 443: whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; ! 444: ! 445: for (block = startBlock; block < endBlock; block++) ! 446: { ! 447: *bufPtr++ ^= *whiteningValuesPtr64--; ! 448: *bufPtr++ ^= *whiteningValuesPtr64--; ! 449: } ! 450: ! 451: blockCount -= endBlock - startBlock; ! 452: startBlock = 0; ! 453: dataUnitNo++; ! 454: ! 455: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); ! 456: } ! 457: ! 458: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); ! 459: FAST_ERASE64 (whiteningValues, sizeof (whiteningValues)); ! 460: } ! 461: ! 462: ! 463: // Optimized for encryption algorithms not supporting intra-data-unit parallelization ! 464: static void DecryptBufferXTSNonParallel (unsigned __int8 *buffer, ! 465: TC_LARGEST_COMPILER_UINT length, ! 466: const UINT64_STRUCT *startDataUnitNo, ! 467: unsigned int startCipherBlockNo, ! 468: unsigned __int8 *ks, ! 469: unsigned __int8 *ks2, ! 470: int cipher) ! 471: { 1.1 root 472: unsigned __int8 finalCarry; 473: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; 474: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; 475: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; 476: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; 477: unsigned int startBlock = startCipherBlockNo, endBlock, block; 478: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; 1.1.1.3 root 479: 1.1 root 480: // Convert the 64-bit data unit number into a little-endian 16-byte array. 481: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. 482: dataUnitNo = startDataUnitNo->Value; 483: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); 484: *((unsigned __int64 *) byteBufUnitNo + 1) = 0; 485: 486: if (length % BYTES_PER_XTS_BLOCK) 487: TC_THROW_FATAL_EXCEPTION; 488: 489: blockCount = length / BYTES_PER_XTS_BLOCK; 490: 491: // Process all blocks in the buffer 492: while (blockCount > 0) 493: { 494: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) 495: endBlock = startBlock + (unsigned int) blockCount; 496: else 497: endBlock = BLOCKS_PER_XTS_DATA_UNIT; 498: 499: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; 500: 501: // Encrypt the data unit number using the secondary key (in order to generate the first 502: // whitening value for this data unit) 503: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); 504: *(whiteningValuePtr64 + 1) = 0; 505: EncipherBlock (cipher, whiteningValue, ks2); 506: 1.1.1.3 root 507: // Generate (and apply) subsequent whitening values for blocks in this data unit and 508: // decrypt all relevant blocks in this data unit 1.1 root 509: for (block = 0; block < endBlock; block++) 510: { 511: if (block >= startBlock) 512: { 1.1.1.3 root 513: // Post-whitening 514: *bufPtr++ ^= *whiteningValuePtr64++; 515: *bufPtr-- ^= *whiteningValuePtr64--; 516: 517: // Actual decryption 518: DecipherBlock (cipher, bufPtr, ks); 519: 520: // Pre-whitening 521: *bufPtr++ ^= *whiteningValuePtr64++; 522: *bufPtr++ ^= *whiteningValuePtr64; 1.1 root 523: } 524: else 525: whiteningValuePtr64++; 526: 527: // Derive the next whitening value 528: 529: #if BYTE_ORDER == LITTLE_ENDIAN 530: 1.1.1.3 root 531: // Little-endian platforms 1.1 root 532: 533: finalCarry = 534: (*whiteningValuePtr64 & 0x8000000000000000) ? 535: 135 : 0; 536: 537: *whiteningValuePtr64-- <<= 1; 538: 539: if (*whiteningValuePtr64 & 0x8000000000000000) 540: *(whiteningValuePtr64 + 1) |= 1; 541: 542: *whiteningValuePtr64 <<= 1; 543: 544: #else 1.1.1.3 root 545: // Big-endian platforms 1.1 root 546: 547: finalCarry = 548: (*whiteningValuePtr64 & 0x80) ? 549: 135 : 0; 550: 551: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); 552: 553: whiteningValuePtr64--; 554: 555: if (*whiteningValuePtr64 & 0x80) 556: *(whiteningValuePtr64 + 1) |= 0x0100000000000000; 557: 558: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); 559: #endif 560: 561: whiteningValue[0] ^= finalCarry; 562: } 563: 1.1.1.3 root 564: blockCount -= endBlock - startBlock; 1.1 root 565: startBlock = 0; 566: dataUnitNo++; 567: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); 568: } 569: 1.1.1.3 root 570: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); 1.1 root 571: } 572: 573: 1.1.1.3 root 574: #else // TC_NO_COMPILER_INT64 1.1 root 575: 1.1.1.3 root 576: /* ---- The following code is to be used only when native 64-bit data types are not available. ---- */ 1.1 root 577: 578: #if BYTE_ORDER == BIG_ENDIAN 1.1.1.3 root 579: #error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms 1.1 root 580: #endif 581: 582: 583: // Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit 584: // environments/platforms) into a little-endian 16-byte array. 585: static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32) 586: { 587: unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf; 588: 589: *bufPtr32++ = lowInt32; 590: *bufPtr32++ = highInt32; 591: 592: // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes 593: *bufPtr32++ = 0; 594: *bufPtr32 = 0; 595: } 596: 597: 1.1.1.3 root 598: // Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters, 599: // see the 64-bit version of EncryptBufferXTS(). 600: static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer, 1.1 root 601: TC_LARGEST_COMPILER_UINT length, 602: const UINT64_STRUCT *startDataUnitNo, 603: unsigned int startBlock, 1.1.1.3 root 604: unsigned __int8 *ks, 1.1 root 605: unsigned __int8 *ks2, 1.1.1.3 root 606: int cipher, 607: BOOL decryption) 1.1 root 608: { 609: TC_LARGEST_COMPILER_UINT blockCount; 610: UINT64_STRUCT dataUnitNo; 611: unsigned int block; 612: unsigned int endBlock; 613: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; 614: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; 615: unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer; 616: unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; 617: unsigned __int8 finalCarry; 618: unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1; 619: 620: // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms 621: dataUnitNo.HighPart = startDataUnitNo->HighPart; 622: dataUnitNo.LowPart = startDataUnitNo->LowPart; 623: 624: blockCount = length / BYTES_PER_XTS_BLOCK; 625: 626: // Convert the 64-bit data unit number into a little-endian 16-byte array. 627: // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.) 628: Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); 629: 630: // Generate whitening values for all blocks in the buffer 631: while (blockCount > 0) 632: { 633: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) 634: endBlock = startBlock + (unsigned int) blockCount; 635: else 636: endBlock = BLOCKS_PER_XTS_DATA_UNIT; 637: 638: // Encrypt the data unit number using the secondary key (in order to generate the first 639: // whitening value for this data unit) 640: memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK); 641: EncipherBlock (cipher, whiteningValue, ks2); 642: 1.1.1.3 root 643: // Generate (and apply) subsequent whitening values for blocks in this data unit and 644: // encrypt/decrypt all relevant blocks in this data unit 1.1 root 645: for (block = 0; block < endBlock; block++) 646: { 647: if (block >= startBlock) 648: { 649: whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; 650: 1.1.1.3 root 651: // Whitening 1.1 root 652: *bufPtr32++ ^= *whiteningValuePtr32++; 653: *bufPtr32++ ^= *whiteningValuePtr32++; 654: *bufPtr32++ ^= *whiteningValuePtr32++; 1.1.1.3 root 655: *bufPtr32 ^= *whiteningValuePtr32; 656: 657: bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1; 658: 659: // Actual encryption/decryption 660: if (decryption) 661: DecipherBlock (cipher, bufPtr32, ks); 662: else 663: EncipherBlock (cipher, bufPtr32, ks); 664: 665: whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; 1.1 root 666: 1.1.1.3 root 667: // Whitening 668: *bufPtr32++ ^= *whiteningValuePtr32++; 669: *bufPtr32++ ^= *whiteningValuePtr32++; 670: *bufPtr32++ ^= *whiteningValuePtr32++; 671: *bufPtr32++ ^= *whiteningValuePtr32; 1.1 root 672: } 673: 674: // Derive the next whitening value 675: 676: finalCarry = 0; 677: 678: for (whiteningValuePtr32 = finalDwordWhiteningValuePtr; 679: whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue; 680: whiteningValuePtr32--) 681: { 682: if (*whiteningValuePtr32 & 0x80000000) // If the following shift results in a carry 683: { 684: if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word 685: { 686: // A regular carry 687: *(whiteningValuePtr32 + 1) |= 1; 688: } 689: else 690: { 691: // The highest byte shift will result in a carry 692: finalCarry = 135; 693: } 694: } 695: 696: *whiteningValuePtr32 <<= 1; 697: } 698: 699: whiteningValue[0] ^= finalCarry; 700: } 701: 1.1.1.3 root 702: blockCount -= endBlock - startBlock; 1.1 root 703: startBlock = 0; 704: 705: // Increase the data unit number by one 1.1.1.3 root 706: if (!++dataUnitNo.LowPart) 707: { 708: dataUnitNo.HighPart++; 709: } 1.1 root 710: 711: // Convert the 64-bit data unit number into a little-endian 16-byte array. 712: Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); 713: } 714: 1.1.1.3 root 715: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); 1.1 root 716: } 717: 718: 1.1.1.3 root 719: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above. 1.1 root 720: void EncryptBufferXTS (unsigned __int8 *buffer, 721: TC_LARGEST_COMPILER_UINT length, 1.1.1.3 root 722: const UINT64_STRUCT *startDataUnitNo, 1.1 root 723: unsigned int startCipherBlockNo, 724: unsigned __int8 *ks, 725: unsigned __int8 *ks2, 726: int cipher) 727: { 728: // Encrypt all plaintext blocks in the buffer 1.1.1.3 root 729: EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE); 1.1 root 730: } 731: 732: 1.1.1.3 root 733: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS(). 1.1 root 734: void DecryptBufferXTS (unsigned __int8 *buffer, 735: TC_LARGEST_COMPILER_UINT length, 1.1.1.3 root 736: const UINT64_STRUCT *startDataUnitNo, 1.1 root 737: unsigned int startCipherBlockNo, 738: unsigned __int8 *ks, 739: unsigned __int8 *ks2, 740: int cipher) 741: { 1.1.1.3 root 742: // Decrypt all ciphertext blocks in the buffer 743: EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE); 1.1 root 744: } 745: 1.1.1.3 root 746: #endif // TC_NO_COMPILER_INT64
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.