|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
1.1.1.6 ! root 4: Governed by the TrueCrypt License 2.8 the full text of which is contained
1.1 root 5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
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: {
49: unsigned __int8 finalCarry;
50: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
51: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
52: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
53: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
54: unsigned int startBlock = startCipherBlockNo, endBlock, block;
55: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
56:
57: /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
58: finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
59: number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
60: as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
61: the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
62: derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
63:
64: // Convert the 64-bit data unit number into a little-endian 16-byte array.
65: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
66: dataUnitNo = startDataUnitNo->Value;
67: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
68: *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
69:
70: if (length % BYTES_PER_XTS_BLOCK)
71: TC_THROW_FATAL_EXCEPTION;
72:
73: blockCount = length / BYTES_PER_XTS_BLOCK;
74:
75: // Process all blocks in the buffer
76: while (blockCount > 0)
77: {
78: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
79: endBlock = startBlock + (unsigned int) blockCount;
80: else
81: endBlock = BLOCKS_PER_XTS_DATA_UNIT;
82:
83: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
84:
85: // Encrypt the data unit number using the secondary key (in order to generate the first
86: // whitening value for this data unit)
87: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
88: *(whiteningValuePtr64 + 1) = 0;
89: EncipherBlock (cipher, whiteningValue, ks2);
90:
1.1.1.3 root 91: // Generate (and apply) subsequent whitening values for blocks in this data unit and
92: // encrypt all relevant blocks in this data unit
1.1 root 93: for (block = 0; block < endBlock; block++)
94: {
95: if (block >= startBlock)
96: {
1.1.1.3 root 97: // Pre-whitening
98: *bufPtr++ ^= *whiteningValuePtr64++;
99: *bufPtr-- ^= *whiteningValuePtr64--;
100:
101: // Actual encryption
102: EncipherBlock (cipher, bufPtr, ks);
103:
104: // Post-whitening
105: *bufPtr++ ^= *whiteningValuePtr64++;
106: *bufPtr++ ^= *whiteningValuePtr64;
1.1 root 107: }
108: else
109: whiteningValuePtr64++;
110:
111: // Derive the next whitening value
112:
113: #if BYTE_ORDER == LITTLE_ENDIAN
114:
1.1.1.3 root 115: // Little-endian platforms
1.1 root 116:
117: finalCarry =
118: (*whiteningValuePtr64 & 0x8000000000000000) ?
119: 135 : 0;
120:
121: *whiteningValuePtr64-- <<= 1;
122:
123: if (*whiteningValuePtr64 & 0x8000000000000000)
124: *(whiteningValuePtr64 + 1) |= 1;
125:
126: *whiteningValuePtr64 <<= 1;
127: #else
1.1.1.3 root 128:
129: // Big-endian platforms
1.1 root 130:
131: finalCarry =
132: (*whiteningValuePtr64 & 0x80) ?
133: 135 : 0;
134:
135: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
136:
137: whiteningValuePtr64--;
138:
139: if (*whiteningValuePtr64 & 0x80)
140: *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
141:
142: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
143: #endif
144:
145: whiteningValue[0] ^= finalCarry;
146: }
147:
1.1.1.3 root 148: blockCount -= endBlock - startBlock;
1.1 root 149: startBlock = 0;
150: dataUnitNo++;
151: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
152: }
153:
1.1.1.3 root 154: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1 root 155: }
156:
157:
158: // For descriptions of the input parameters, see EncryptBufferXTS().
159: void DecryptBufferXTS (unsigned __int8 *buffer,
160: TC_LARGEST_COMPILER_UINT length,
161: const UINT64_STRUCT *startDataUnitNo,
162: unsigned int startCipherBlockNo,
163: unsigned __int8 *ks,
164: unsigned __int8 *ks2,
165: int cipher)
166: {
167: unsigned __int8 finalCarry;
168: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
169: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
170: unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
171: unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
172: unsigned int startBlock = startCipherBlockNo, endBlock, block;
173: TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
1.1.1.3 root 174:
1.1 root 175: // Convert the 64-bit data unit number into a little-endian 16-byte array.
176: // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
177: dataUnitNo = startDataUnitNo->Value;
178: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
179: *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
180:
181: if (length % BYTES_PER_XTS_BLOCK)
182: TC_THROW_FATAL_EXCEPTION;
183:
184: blockCount = length / BYTES_PER_XTS_BLOCK;
185:
186: // Process all blocks in the buffer
187: while (blockCount > 0)
188: {
189: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
190: endBlock = startBlock + (unsigned int) blockCount;
191: else
192: endBlock = BLOCKS_PER_XTS_DATA_UNIT;
193:
194: whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
195:
196: // Encrypt the data unit number using the secondary key (in order to generate the first
197: // whitening value for this data unit)
198: *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
199: *(whiteningValuePtr64 + 1) = 0;
200: EncipherBlock (cipher, whiteningValue, ks2);
201:
1.1.1.3 root 202: // Generate (and apply) subsequent whitening values for blocks in this data unit and
203: // decrypt all relevant blocks in this data unit
1.1 root 204: for (block = 0; block < endBlock; block++)
205: {
206: if (block >= startBlock)
207: {
1.1.1.3 root 208: // Post-whitening
209: *bufPtr++ ^= *whiteningValuePtr64++;
210: *bufPtr-- ^= *whiteningValuePtr64--;
211:
212: // Actual decryption
213: DecipherBlock (cipher, bufPtr, ks);
214:
215: // Pre-whitening
216: *bufPtr++ ^= *whiteningValuePtr64++;
217: *bufPtr++ ^= *whiteningValuePtr64;
1.1 root 218: }
219: else
220: whiteningValuePtr64++;
221:
222: // Derive the next whitening value
223:
224: #if BYTE_ORDER == LITTLE_ENDIAN
225:
1.1.1.3 root 226: // Little-endian platforms
1.1 root 227:
228: finalCarry =
229: (*whiteningValuePtr64 & 0x8000000000000000) ?
230: 135 : 0;
231:
232: *whiteningValuePtr64-- <<= 1;
233:
234: if (*whiteningValuePtr64 & 0x8000000000000000)
235: *(whiteningValuePtr64 + 1) |= 1;
236:
237: *whiteningValuePtr64 <<= 1;
238:
239: #else
1.1.1.3 root 240: // Big-endian platforms
1.1 root 241:
242: finalCarry =
243: (*whiteningValuePtr64 & 0x80) ?
244: 135 : 0;
245:
246: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
247:
248: whiteningValuePtr64--;
249:
250: if (*whiteningValuePtr64 & 0x80)
251: *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
252:
253: *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
254: #endif
255:
256: whiteningValue[0] ^= finalCarry;
257: }
258:
1.1.1.3 root 259: blockCount -= endBlock - startBlock;
1.1 root 260: startBlock = 0;
261: dataUnitNo++;
262: *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
263: }
264:
1.1.1.3 root 265: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1 root 266: }
267:
268:
269:
1.1.1.3 root 270: #else // TC_NO_COMPILER_INT64
1.1 root 271:
1.1.1.3 root 272: /* ---- The following code is to be used only when native 64-bit data types are not available. ---- */
1.1 root 273:
274: #if BYTE_ORDER == BIG_ENDIAN
1.1.1.3 root 275: #error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms
1.1 root 276: #endif
277:
278:
279: // Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit
280: // environments/platforms) into a little-endian 16-byte array.
281: static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32)
282: {
283: unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf;
284:
285: *bufPtr32++ = lowInt32;
286: *bufPtr32++ = highInt32;
287:
288: // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes
289: *bufPtr32++ = 0;
290: *bufPtr32 = 0;
291: }
292:
293:
1.1.1.3 root 294: // Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters,
295: // see the 64-bit version of EncryptBufferXTS().
296: static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer,
1.1 root 297: TC_LARGEST_COMPILER_UINT length,
298: const UINT64_STRUCT *startDataUnitNo,
299: unsigned int startBlock,
1.1.1.3 root 300: unsigned __int8 *ks,
1.1 root 301: unsigned __int8 *ks2,
1.1.1.3 root 302: int cipher,
303: BOOL decryption)
1.1 root 304: {
305: TC_LARGEST_COMPILER_UINT blockCount;
306: UINT64_STRUCT dataUnitNo;
307: unsigned int block;
308: unsigned int endBlock;
309: unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
310: unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
311: unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer;
312: unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
313: unsigned __int8 finalCarry;
314: unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1;
315:
316: // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms
317: dataUnitNo.HighPart = startDataUnitNo->HighPart;
318: dataUnitNo.LowPart = startDataUnitNo->LowPart;
319:
320: blockCount = length / BYTES_PER_XTS_BLOCK;
321:
322: // Convert the 64-bit data unit number into a little-endian 16-byte array.
323: // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.)
324: Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
325:
326: // Generate whitening values for all blocks in the buffer
327: while (blockCount > 0)
328: {
329: if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
330: endBlock = startBlock + (unsigned int) blockCount;
331: else
332: endBlock = BLOCKS_PER_XTS_DATA_UNIT;
333:
334: // Encrypt the data unit number using the secondary key (in order to generate the first
335: // whitening value for this data unit)
336: memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK);
337: EncipherBlock (cipher, whiteningValue, ks2);
338:
1.1.1.3 root 339: // Generate (and apply) subsequent whitening values for blocks in this data unit and
340: // encrypt/decrypt all relevant blocks in this data unit
1.1 root 341: for (block = 0; block < endBlock; block++)
342: {
343: if (block >= startBlock)
344: {
345: whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
346:
1.1.1.3 root 347: // Whitening
1.1 root 348: *bufPtr32++ ^= *whiteningValuePtr32++;
349: *bufPtr32++ ^= *whiteningValuePtr32++;
350: *bufPtr32++ ^= *whiteningValuePtr32++;
1.1.1.3 root 351: *bufPtr32 ^= *whiteningValuePtr32;
352:
353: bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1;
354:
355: // Actual encryption/decryption
356: if (decryption)
357: DecipherBlock (cipher, bufPtr32, ks);
358: else
359: EncipherBlock (cipher, bufPtr32, ks);
360:
361: whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
1.1 root 362:
1.1.1.3 root 363: // Whitening
364: *bufPtr32++ ^= *whiteningValuePtr32++;
365: *bufPtr32++ ^= *whiteningValuePtr32++;
366: *bufPtr32++ ^= *whiteningValuePtr32++;
367: *bufPtr32++ ^= *whiteningValuePtr32;
1.1 root 368: }
369:
370: // Derive the next whitening value
371:
372: finalCarry = 0;
373:
374: for (whiteningValuePtr32 = finalDwordWhiteningValuePtr;
375: whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue;
376: whiteningValuePtr32--)
377: {
378: if (*whiteningValuePtr32 & 0x80000000) // If the following shift results in a carry
379: {
380: if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word
381: {
382: // A regular carry
383: *(whiteningValuePtr32 + 1) |= 1;
384: }
385: else
386: {
387: // The highest byte shift will result in a carry
388: finalCarry = 135;
389: }
390: }
391:
392: *whiteningValuePtr32 <<= 1;
393: }
394:
395: whiteningValue[0] ^= finalCarry;
396: }
397:
1.1.1.3 root 398: blockCount -= endBlock - startBlock;
1.1 root 399: startBlock = 0;
400:
401: // Increase the data unit number by one
1.1.1.3 root 402: if (!++dataUnitNo.LowPart)
403: {
404: dataUnitNo.HighPart++;
405: }
1.1 root 406:
407: // Convert the 64-bit data unit number into a little-endian 16-byte array.
408: Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
409: }
410:
1.1.1.3 root 411: FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1 root 412: }
413:
414:
1.1.1.3 root 415: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above.
1.1 root 416: void EncryptBufferXTS (unsigned __int8 *buffer,
417: TC_LARGEST_COMPILER_UINT length,
1.1.1.3 root 418: const UINT64_STRUCT *startDataUnitNo,
1.1 root 419: unsigned int startCipherBlockNo,
420: unsigned __int8 *ks,
421: unsigned __int8 *ks2,
422: int cipher)
423: {
424: // Encrypt all plaintext blocks in the buffer
1.1.1.3 root 425: EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE);
1.1 root 426: }
427:
428:
1.1.1.3 root 429: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS().
1.1 root 430: void DecryptBufferXTS (unsigned __int8 *buffer,
431: TC_LARGEST_COMPILER_UINT length,
1.1.1.3 root 432: const UINT64_STRUCT *startDataUnitNo,
1.1 root 433: unsigned int startCipherBlockNo,
434: unsigned __int8 *ks,
435: unsigned __int8 *ks2,
436: int cipher)
437: {
1.1.1.3 root 438: // Decrypt all ciphertext blocks in the buffer
439: EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE);
1.1 root 440: }
441:
1.1.1.3 root 442: #endif // TC_NO_COMPILER_INT64
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.