VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Resource.h
blob: 7106b3b81728ff4dc81e22fc76f39f01e676e7e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Common.rc
//
#define IDI_TRUECRYPT_ICON              501
#define IDI_TRUECRYPT_VOL_ICON          502
#define IDD_BENCHMARK_DLG               503
#define IDD_MOUNT_OPTIONS               504
#define IDD_KEYFILES                    505
#define IDR_LANGUAGE                    506
#define IDI_TRUECRYPT                   507
#define IDD_ABOUT_DLG                   508
#define IDD_COMMANDHELP_DLG             509
#define IDD_RAWDEVICES_DLG              510
#define IDC_HOMEPAGE                    511
#define IDR_COMMON_RSRC_HEADER          512
#define IDD_LANGUAGE                    513
#define IDD_CIPHER_TEST_DLG             514
#define IDR_LICENSE                     515
#define IDD_AUXILIARY_DLG               516
#define IDB_TEXTUAL_LOGO_BKG            517
#define IDB_TEXTUAL_LOGO_96DPI          518
#define IDB_TEXTUAL_LOGO_288DPI         519
#define IDR_BOOT_SECTOR                 520
#define IDR_BOOT_SECTOR_AES             521
#define IDR_BOOT_SECTOR_SERPENT         522
#define IDR_BOOT_SECTOR_TWOFISH         523
#define IDR_BOOT_LOADER_DECOMPRESSOR    524
#define IDR_BOOT_LOADER                 525
#define IDR_BOOT_LOADER_AES             526
#define IDR_BOOT_LOADER_SERPENT         527
#define IDR_BOOT_LOADER_TWOFISH         528
#define IDR_RESCUE_BOOT_SECTOR          529
#define IDR_RESCUE_BOOT_SECTOR_AES      530
#define IDR_RESCUE_BOOT_SECTOR_SERPENT  531
#define IDR_RESCUE_BOOT_SECTOR_TWOFISH  532
#define IDR_RESCUE_LOADER               533
#define IDR_RESCUE_LOADER_AES           534
#define IDR_RESCUE_LOADER_SERPENT       535
#define IDR_RESCUE_LOADER_TWOFISH       536
#define IDD_TOKEN_PASSWORD              537
#define IDD_TOKEN_KEYFILES              538
#define IDD_NEW_TOKEN_KEYFILE           539
#define IDD_RANDOM_POOL_ENRICHMENT      540
#define IDI_TRUECRYPT_MOUNTED_ICON      541
#define IDR_BOOT_SECTOR_SHA2            542
#define IDR_BOOT_SECTOR_AES_SHA2        543
#define IDR_BOOT_SECTOR_SERPENT_SHA2    544
#define IDR_BOOT_SECTOR_TWOFISH_SHA2    545
#define IDR_BOOT_LOADER_SHA2            546
#define IDR_BOOT_LOADER_AES_SHA2        547
#define IDR_BOOT_LOADER_SERPENT_SHA2    548
#define IDR_BOOT_LOADER_TWOFISH_SHA2    549
#define IDR_RESCUE_BOOT_SECTOR_SHA2     550
#define IDR_RESCUE_BOOT_SECTOR_AES_SHA2 551
#define IDR_RESCUE_BOOT_SECTOR_SERPENT_SHA2 552
#define IDR_RESCUE_BOOT_SECTOR_TWOFISH_SHA2 553
#define IDR_RESCUE_LOADER_SHA2          554
#define IDR_RESCUE_LOADER_AES_SHA2      555
#define IDR_RESCUE_LOADER_SERPENT_SHA2  556
#define IDR_RESCUE_LOADER_TWOFISH_SHA2  557
#define IDR_BOOT_SECTOR_CAMELLIA        558
#define IDR_BOOT_LOADER_CAMELLIA        559
#define IDR_RESCUE_BOOT_SECTOR_CAMELLIA 560
#define IDR_RESCUE_LOADER_CAMELLIA      561
#define IDR_BOOT_SECTOR_CAMELLIA_SHA2   562
#define IDR_BOOT_LOADER_CAMELLIA_SHA2   563
#define IDR_RESCUE_BOOT_SECTOR_CAMELLIA_SHA2 564
#define IDR_RESCUE_LOADER_CAMELLIA_SHA2 565
#define IDR_EFI_DCSBOOT                 566
#define IDR_EFI_DCSINT                  567
#define IDR_EFI_DCSCFG                  568
#define IDR_EFI_LEGACYSPEAKER           569
#define IDR_EFI_DCSBML                  570
#define IDR_EFI_DCSRE                   571
#define IDR_EFI_DCSBOOT32               572
#define IDR_EFI_DCSINT32                573
#define IDR_EFI_DCSCFG32                574
#define IDR_EFI_LEGACYSPEAKER32         575
#define IDR_EFI_DCSBML32                576
#define IDR_EFI_DCSRE32                 577
#define IDR_EFI_DCSINFO                 578
#define IDR_EFI_DCSINFO32               579
#define IDC_HW_AES_LABEL_LINK           5000
#define IDC_HW_AES                      5001
#define IDC_PARALLELIZATION_LABEL_LINK  5002
#define IDC_PARALLELIZATION             5003
#define IDT_TOKEN_PASSWORD              5004
#define IDC_PRINT                       5005
#define IDC_KEY                         5006
#define IDC_PLAINTEXT                   5007
#define IDC_CIPHERTEXT                  5008
#define IDC_INFO_BOX_TEXT               5009
#define IDC_SECONDARY_KEY               5010
#define IDD_TEXT_INFO_DIALOG_BOX_DLG    5011
#define IDC_TEST_DATA_UNIT_NUMBER       5012
#define IDD_KEYFILE_GENERATOR           5013
#define IDC_CIPHER                      5014
#define IDD_MULTI_CHOICE_DLG            5015
#define IDC_TEST_BLOCK_NUMBER           5016
#define IDD_STATIC_MODELESS_WAIT_DLG    5017
#define IDC_POOL_CONTENTS               5018
#define IDC_PRF_ID                      5019
#define IDC_KEY_SIZE                    5020
#define IDC_PLAINTEXT_SIZE              5021
#define IDC_REDTICK                     5022
#define IDC_TESTS_MESSAGE               5023
#define IDC_RESET                       5024
#define IDC_AUTO                        5025
#define IDC_DECRYPT                     5026
#define IDT_TEST_KEY                    5027
#define IDT_TEST_PLAINTEXT              5028
#define IDT_PRF                         5029
#define IDT_XTS_MODE                    5030
#define IDT_TEST_CIPHERTEXT             5031
#define IDT_KEY                         5032
#define IDT_PLAINTEXT                   5033
#define IDC_ENCRYPT                     5034
#define IDT_KEY_UNIT                    5035
#define IDT_CIPHER                      5036
#define IDT_PLAINTEXT_SIZE_UNIT         5037
#define IDC_DEVICELIST                  5038
#define IDT_TEST_BLOCK_NUMBER           5039
#define IDT_SECONDARY_KEY               5040
#define IDC_PERFORM_BENCHMARK           5041
#define IDT_TEST_DATA_UNIT_NUMBER       5042
#define IDC_KEYFILES_HIDVOL_PROT        5043
#define IDC_KEYLIST                     5044
#define IDC_ABOUT_BKG                   5045
#define IDT_ABOUT_VERSION               5046
#define IDT_BOX_BENCHMARK_INFO          5047
#define IDC_ABOUT_CREDITS               5048
#define IDT_SORT_METHOD                 5049
#define IDC_MOUNT_READONLY              5050
#define IDC_MOUNT_REMOVABLE             5051
#define IDC_PROTECT_HIDDEN_VOL          5052
#define IDC_COMMANDHELP_TEXT            5053
#define IDC_USE_EMBEDDED_HEADER_BAK     5054
#define IDC_MOUNT_SYSENC_PART_WITHOUT_PBA 5055
#define IDT_HIDDEN_PROT_PASSWD          5056
#define IDC_RESULTS                     5057
#define IDC_KEYADD                      5058
#define IDC_KEYREMOVE                   5059
#define IDC_KEYREMOVEALL                5060
#define IDC_KEYFILES_ENABLE             5061
#define IDT_HIDDEN_VOL_PROTECTION       5062
#define IDC_ADD_KEYFILE_PATH            5063
#define IDC_BENCHMARK_BUFFER_SIZE       5064
#define IDC_SHOW_PASSWORD_MO            5065
#define IDC_GENERATE_KEYFILE            5066
#define IDC_BENCHMARK_SORT_METHOD       5067
#define IDC_PASSWORD_PROT_HIDVOL        5068
#define IDT_BUFFER_SIZE                 5069
#define IDC_LANGLIST                    5070
#define IDC_KEYFILES_ENABLE_HIDVOL_PROT 5071
#define IDT_KEYFILES_NOTE               5072
#define IDT_KEYFILE_WARNING             5073
#define IDT_KEYFILE_GENERATOR_NOTE      5074
#define IDC_GENERATE_AND_SAVE_KEYFILE   5075
#define IDT_POOL_CONTENTS               5076
#define IDC_GET_LANG_PACKS              5077
#define IDT_LANGPACK_AUTHORS            5078
#define IDC_LANGPACK_CREDITS            5079
#define IDC_LANGPACK_VERSION            5080
#define IDT_ACTIVE_LANG_PACK            5081
#define IDC_DISPLAY_POOL_CONTENTS       5082
#define IDC_XTS_MODE_ENABLED            5083
#define IDC_MULTI_CHOICE_MSG            5084
#define IDC_CHOICE1                     5085
#define IDC_CHOICE5                     5086
#define IDC_CHOICE2                     5087
#define IDC_CHOICE3                     5088
#define IDC_CHOICE4                     5089
#define IDC_CHOICE6                     5090
#define IDC_CHOICE7                     5091
#define IDC_CHOICE8                     5092
#define IDC_CHOICE9                     5093
#define IDC_CHOICE10                    5094
#define IDC_MC_DLG_HR1                  5095
#define IDC_MC_DLG_HR2                  5096
#define IDC_LINK_HIDVOL_PROTECTION_INFO 5097
#define IDC_LINK_KEYFILES_INFO          5098
#define IDC_TEXTUAL_LOGO_IMG            5099
#define IDC_ASPECT_RATIO_CALIBRATION_BOX 5100
#define IDC_ABOUT_LOGO_AREA             5101
#define IDC_TOKEN_PASSWORD              5102
#define IDC_TOKEN_FILE_LIST             5103
#define IDC_TOKEN_FILES_ADD             5104
#define IDC_EXPORT                      5105
#define IDC_DELETE                      5106
#define IDC_IMPORT_KEYFILE              5107
#define IDC_SELECTED_TOKEN              5108
#define IDT_SECURITY_TOKEN              5109
#define IDT_TOKEN_KEYFILE_NAME          5110
#define IDC_TOKEN_KEYFILE_NAME          5111
#define IDT_TOKEN_PASSWORD_INFO         5112
#define IDT_RANDOM_POOL_ENRICHMENT_NOTE 5113
#define IDC_CONTINUE                    5114
#define IDT_ABOUT_RELEASE               5115
#define IDT_STATIC_MODELESS_WAIT_DLG_INFO 5116
#define IDT_NUMBER_KEYFILES             5117
#define IDC_NUMBER_KEYFILES             5118
#define IDT_KEYFILES_BASE_NAME          5119
#define IDC_KEYFILES_BASE_NAME          5120
#define IDC_KEYFILES_SIZE               5121
#define IDC_KEYFILES_RANDOM_SIZE        5122
#define IDT_KEYFILES_SIZE               5123
#define IDD_STATIC_MODAL_WAIT_DLG       5124
#define IDT_STATIC_MODAL_WAIT_DLG_INFO  5125
#define IDC_WAIT_PROGRESS_BAR           5126
#define IDC_PKCS5_PRF_ID                5127
#define IDT_PKCS5_PRF                   5128
#define IDT_PIM                         5129
#define IDC_PIM                         5130
#define IDC_PIM_HELP                    5131
#define IDC_PIM_ENABLE                  5132
#define IDC_VOLUME_LABEL                5133
#define IDT_VOLUME_LABEL                5134
#define IDC_KEYFILES_TRY_EMPTY_PASSWORD 5135
#define IDC_ENTROPY_BAR                 5136
#define IDT_ENTROPY_BAR                 5137
#define IDT_BENCHMARK                   5138
#define IDC_BENCHMARK_LIST              5139
#define IDC_BENCHMARK_PREBOOT           5140
#define IDD_TEXT_EDIT_DLG               5141

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        578
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         5141
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.

 Governed by the TrueCrypt License 3.0 the full text of which is contained in
 the file License.txt included in TrueCrypt binary and source code distribution
 packages.
*/

/* If native 64-bit data types are not available, define TC_NO_COMPILER_INT64. 

For big-endian platforms define BYTE_ORDER as BIG_ENDIAN. */


#ifdef TC_MINIMIZE_CODE_SIZE
//	Preboot/boot version
#	ifndef TC_NO_COMPILER_INT64
#		define TC_NO_COMPILER_INT64
#	endif
#	pragma optimize ("tl", on)
#endif

#ifdef TC_NO_COMPILER_INT64
#	include <memory.h>
#endif

#include "Xts.h"


#ifndef TC_NO_COMPILER_INT64

// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size
// ks: the primary key schedule
// ks2: the secondary key schedule
// startDataUnitNo: The sequential number of the data unit with which the buffer starts.
// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo.
//                     When encrypting the data unit from its first block, startCipherBlockNo is 0. 
//                     The startCipherBlockNo value applies only to the first data unit in the buffer; each successive
//                     data unit is encrypted from its first block. The start of the buffer does not have to be
//                     aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it
//                     is not aligned, startCipherBlockNo must reflect the misalignment accordingly.
void EncryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	if (CipherSupportsIntraDataUnitParallelization (cipher))
		EncryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
	else
		EncryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
}


// Optimized for encryption algorithms supporting intra-data-unit parallelization
static void EncryptBufferXTSParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned __int64 *dataUnitBufPtr;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	/* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
	finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
	number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
	as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
	the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
	derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
		// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				*whiteningValuesPtr64-- = *whiteningValuePtr64++;
				*whiteningValuesPtr64-- = *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;
#else

			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		dataUnitBufPtr = bufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		// Encrypt all blocks in this data unit

		for (block = startBlock; block < endBlock; block++)
		{
			// Pre-whitening
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		// Actual encryption
		EncipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);
		
		bufPtr = dataUnitBufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		for (block = startBlock; block < endBlock; block++)
		{
			// Post-whitening
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
	FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}


// Optimized for encryption algorithms not supporting intra-data-unit parallelization
static void EncryptBufferXTSNonParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	/* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
	finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
	number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
	as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
	the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
	derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// encrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				// Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr-- ^= *whiteningValuePtr64--;

				// Actual encryption
				EncipherBlock (cipher, bufPtr, ks);

				// Post-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr++ ^= *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;
#else

			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}


// For descriptions of the input parameters, see EncryptBufferXTS().
void DecryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	if (CipherSupportsIntraDataUnitParallelization (cipher))
		DecryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
	else
		DecryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
}


// Optimized for encryption algorithms supporting intra-data-unit parallelization
static void DecryptBufferXTSParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned __int64 *dataUnitBufPtr;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
		// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				*whiteningValuesPtr64-- = *whiteningValuePtr64++;
				*whiteningValuesPtr64-- = *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		dataUnitBufPtr = bufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		// Decrypt blocks in this data unit

		for (block = startBlock; block < endBlock; block++)
		{
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		DecipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);

		bufPtr = dataUnitBufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		for (block = startBlock; block < endBlock; block++)
		{
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;

		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
	FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}


// Optimized for encryption algorithms not supporting intra-data-unit parallelization
static void DecryptBufferXTSNonParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// decrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				// Post-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr-- ^= *whiteningValuePtr64--;

				// Actual decryption
				DecipherBlock (cipher, bufPtr, ks);

				// Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr++ ^= *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}


#else	// TC_NO_COMPILER_INT64

/* ---- The following code is to be used only when native 64-bit data types are not available. ---- */

#if BYTE_ORDER == BIG_ENDIAN
#error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms
#endif 


// Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit
// environments/platforms) into a little-endian 16-byte array.
static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32)
{
	unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf;

	*bufPtr32++ = lowInt32;
	*bufPtr32++ = highInt32;

	// We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes
	*bufPtr32++ = 0;
	*bufPtr32 = 0;
}


// Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters,
// see the 64-bit version of EncryptBufferXTS().
static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer,
							TC_LARGEST_COMPILER_UINT length,
							const UINT64_STRUCT *startDataUnitNo,
							unsigned int startBlock,
							unsigned __int8 *ks,
							unsigned __int8 *ks2,
							int cipher,
							BOOL decryption)
{
	TC_LARGEST_COMPILER_UINT blockCount;
	UINT64_STRUCT dataUnitNo;
	unsigned int block;
	unsigned int endBlock;
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer;
	unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
	unsigned __int8 finalCarry;
	unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1;

	// Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms
	dataUnitNo.HighPart = startDataUnitNo->HighPart;
	dataUnitNo.LowPart = startDataUnitNo->LowPart;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.)
	Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);

	// Generate whitening values for all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK);
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// encrypt/decrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

				// Whitening
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32 ^= *whiteningValuePtr32;

				bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1;

				// Actual encryption/decryption
				if (decryption)
					DecipherBlock (cipher, bufPtr32, ks);
				else
					EncipherBlock (cipher, bufPtr32, ks);

				whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

				// Whitening
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32;
			}

			// Derive the next whitening value

			finalCarry = 0;

			for (whiteningValuePtr32 = finalDwordWhiteningValuePtr;
				whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue;
				whiteningValuePtr32--)
			{
				if (*whiteningValuePtr32 & 0x80000000)	// If the following shift results in a carry
				{
					if (whiteningValuePtr32 != finalDwordWhiteningValuePtr)	// If not processing the highest double word
					{
						// A regular carry
						*(whiteningValuePtr32 + 1) |= 1;
					}
					else 
					{
						// The highest byte shift will result in a carry
						finalCarry = 135;
					}
				}

				*whiteningValuePtr32 <<= 1;
			}

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;

		// Increase the data unit number by one
		if (!++dataUnitNo.LowPart)
		{
			dataUnitNo.HighPart++;
		}

		// Convert the 64-bit data unit number into a little-endian 16-byte array. 
		Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}


// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above.
void EncryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	// Encrypt all plaintext blocks in the buffer
	EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE);
}


// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS().
void DecryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	// Decrypt all ciphertext blocks in the buffer
	EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE);
}

#endif	// TC_NO_COMPILER_INT64