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