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