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