"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Xts.c" (10 Oct 2018, 24671 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Xts.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.18_Source_vs_1.19_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 /* If native 64-bit data types are not available, define TC_NO_COMPILER_INT64.
   14 
   15 For big-endian platforms define BYTE_ORDER as BIG_ENDIAN. */
   16 
   17 
   18 #ifdef TC_MINIMIZE_CODE_SIZE
   19 //  Preboot/boot version
   20 #   ifndef TC_NO_COMPILER_INT64
   21 #       define TC_NO_COMPILER_INT64
   22 #   endif
   23 #   pragma optimize ("tl", on)
   24 #endif
   25 
   26 #ifdef TC_NO_COMPILER_INT64
   27 #   include <memory.h>
   28 #endif
   29 
   30 #include "Xts.h"
   31 
   32 
   33 #ifndef TC_NO_COMPILER_INT64
   34 
   35 // length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size
   36 // ks: the primary key schedule
   37 // ks2: the secondary key schedule
   38 // startDataUnitNo: The sequential number of the data unit with which the buffer starts.
   39 // startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo.
   40 //                     When encrypting the data unit from its first block, startCipherBlockNo is 0.
   41 //                     The startCipherBlockNo value applies only to the first data unit in the buffer; each successive
   42 //                     data unit is encrypted from its first block. The start of the buffer does not have to be
   43 //                     aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it
   44 //                     is not aligned, startCipherBlockNo must reflect the misalignment accordingly.
   45 void EncryptBufferXTS (unsigned __int8 *buffer,
   46                        TC_LARGEST_COMPILER_UINT length,
   47                        const UINT64_STRUCT *startDataUnitNo,
   48                        unsigned int startCipherBlockNo,
   49                        unsigned __int8 *ks,
   50                        unsigned __int8 *ks2,
   51                        int cipher)
   52 {
   53     if (CipherSupportsIntraDataUnitParallelization (cipher))
   54         EncryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
   55     else
   56         EncryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
   57 }
   58 
   59 
   60 // Optimized for encryption algorithms supporting intra-data-unit parallelization
   61 static void EncryptBufferXTSParallel (unsigned __int8 *buffer,
   62                        TC_LARGEST_COMPILER_UINT length,
   63                        const UINT64_STRUCT *startDataUnitNo,
   64                        unsigned int startCipherBlockNo,
   65                        unsigned __int8 *ks,
   66                        unsigned __int8 *ks2,
   67                        int cipher)
   68 {
   69     unsigned __int8 finalCarry;
   70     unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
   71     CRYPTOPP_ALIGN_DATA(16) unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
   72     unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
   73     unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
   74     unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
   75     unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
   76     unsigned __int64 *dataUnitBufPtr;
   77     unsigned int startBlock = startCipherBlockNo, endBlock, block;
   78     unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
   79     TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
   80 
   81     /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
   82     finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
   83     number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
   84     as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
   85     the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
   86     derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
   87 
   88     // Convert the 64-bit data unit number into a little-endian 16-byte array.
   89     // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
   90     dataUnitNo = startDataUnitNo->Value;
   91     *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
   92     *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
   93 
   94     if (length % BYTES_PER_XTS_BLOCK)
   95         TC_THROW_FATAL_EXCEPTION;
   96 
   97     blockCount = length / BYTES_PER_XTS_BLOCK;
   98 
   99     // Process all blocks in the buffer
  100     while (blockCount > 0)
  101     {
  102         if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  103             endBlock = startBlock + (unsigned int) blockCount;
  104         else
  105             endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  106 
  107         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  108         whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  109 
  110         // Encrypt the data unit number using the secondary key (in order to generate the first
  111         // whitening value for this data unit)
  112         *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
  113         *(whiteningValuePtr64 + 1) = 0;
  114         EncipherBlock (cipher, whiteningValue, ks2);
  115 
  116         // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
  117         // whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
  118         for (block = 0; block < endBlock; block++)
  119         {
  120             if (block >= startBlock)
  121             {
  122                 *whiteningValuesPtr64-- = *whiteningValuePtr64++;
  123                 *whiteningValuesPtr64-- = *whiteningValuePtr64;
  124             }
  125             else
  126                 whiteningValuePtr64++;
  127 
  128             // Derive the next whitening value
  129 
  130 #if BYTE_ORDER == LITTLE_ENDIAN
  131 
  132             // Little-endian platforms
  133 
  134             finalCarry =
  135                 (*whiteningValuePtr64 & 0x8000000000000000) ?
  136                 135 : 0;
  137 
  138             *whiteningValuePtr64-- <<= 1;
  139 
  140             if (*whiteningValuePtr64 & 0x8000000000000000)
  141                 *(whiteningValuePtr64 + 1) |= 1;
  142 
  143             *whiteningValuePtr64 <<= 1;
  144 #else
  145 
  146             // Big-endian platforms
  147 
  148             finalCarry =
  149                 (*whiteningValuePtr64 & 0x80) ?
  150                 135 : 0;
  151 
  152             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  153 
  154             whiteningValuePtr64--;
  155 
  156             if (*whiteningValuePtr64 & 0x80)
  157                 *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
  158 
  159             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  160 #endif
  161 
  162             whiteningValue[0] ^= finalCarry;
  163         }
  164 
  165         dataUnitBufPtr = bufPtr;
  166         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  167 
  168         // Encrypt all blocks in this data unit
  169 
  170         for (block = startBlock; block < endBlock; block++)
  171         {
  172             // Pre-whitening
  173             *bufPtr++ ^= *whiteningValuesPtr64--;
  174             *bufPtr++ ^= *whiteningValuesPtr64--;
  175         }
  176 
  177         // Actual encryption
  178         EncipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);
  179 
  180         bufPtr = dataUnitBufPtr;
  181         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  182 
  183         for (block = startBlock; block < endBlock; block++)
  184         {
  185             // Post-whitening
  186             *bufPtr++ ^= *whiteningValuesPtr64--;
  187             *bufPtr++ ^= *whiteningValuesPtr64--;
  188         }
  189 
  190         blockCount -= endBlock - startBlock;
  191         startBlock = 0;
  192         dataUnitNo++;
  193         *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  194     }
  195 
  196     FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  197     FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
  198 }
  199 
  200 
  201 // Optimized for encryption algorithms not supporting intra-data-unit parallelization
  202 static void EncryptBufferXTSNonParallel (unsigned __int8 *buffer,
  203                        TC_LARGEST_COMPILER_UINT length,
  204                        const UINT64_STRUCT *startDataUnitNo,
  205                        unsigned int startCipherBlockNo,
  206                        unsigned __int8 *ks,
  207                        unsigned __int8 *ks2,
  208                        int cipher)
  209 {
  210     unsigned __int8 finalCarry;
  211     CRYPTOPP_ALIGN_DATA(16) unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
  212     unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
  213     unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  214     unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
  215     unsigned int startBlock = startCipherBlockNo, endBlock, block;
  216     TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
  217 
  218     /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
  219     finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
  220     number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
  221     as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
  222     the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
  223     derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
  224 
  225     // Convert the 64-bit data unit number into a little-endian 16-byte array.
  226     // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
  227     dataUnitNo = startDataUnitNo->Value;
  228     *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  229     *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
  230 
  231     if (length % BYTES_PER_XTS_BLOCK)
  232         TC_THROW_FATAL_EXCEPTION;
  233 
  234     blockCount = length / BYTES_PER_XTS_BLOCK;
  235 
  236     // Process all blocks in the buffer
  237     while (blockCount > 0)
  238     {
  239         if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  240             endBlock = startBlock + (unsigned int) blockCount;
  241         else
  242             endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  243 
  244         whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  245 
  246         // Encrypt the data unit number using the secondary key (in order to generate the first
  247         // whitening value for this data unit)
  248         *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
  249         *(whiteningValuePtr64 + 1) = 0;
  250         EncipherBlock (cipher, whiteningValue, ks2);
  251 
  252         // Generate (and apply) subsequent whitening values for blocks in this data unit and
  253         // encrypt all relevant blocks in this data unit
  254         for (block = 0; block < endBlock; block++)
  255         {
  256             if (block >= startBlock)
  257             {
  258                 // Pre-whitening
  259                 *bufPtr++ ^= *whiteningValuePtr64++;
  260                 *bufPtr-- ^= *whiteningValuePtr64--;
  261 
  262                 // Actual encryption
  263                 EncipherBlock (cipher, bufPtr, ks);
  264 
  265                 // Post-whitening
  266                 *bufPtr++ ^= *whiteningValuePtr64++;
  267                 *bufPtr++ ^= *whiteningValuePtr64;
  268             }
  269             else
  270                 whiteningValuePtr64++;
  271 
  272             // Derive the next whitening value
  273 
  274 #if BYTE_ORDER == LITTLE_ENDIAN
  275 
  276             // Little-endian platforms
  277 
  278             finalCarry =
  279                 (*whiteningValuePtr64 & 0x8000000000000000) ?
  280                 135 : 0;
  281 
  282             *whiteningValuePtr64-- <<= 1;
  283 
  284             if (*whiteningValuePtr64 & 0x8000000000000000)
  285                 *(whiteningValuePtr64 + 1) |= 1;
  286 
  287             *whiteningValuePtr64 <<= 1;
  288 #else
  289 
  290             // Big-endian platforms
  291 
  292             finalCarry =
  293                 (*whiteningValuePtr64 & 0x80) ?
  294                 135 : 0;
  295 
  296             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  297 
  298             whiteningValuePtr64--;
  299 
  300             if (*whiteningValuePtr64 & 0x80)
  301                 *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
  302 
  303             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  304 #endif
  305 
  306             whiteningValue[0] ^= finalCarry;
  307         }
  308 
  309         blockCount -= endBlock - startBlock;
  310         startBlock = 0;
  311         dataUnitNo++;
  312         *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  313     }
  314 
  315     FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  316 }
  317 
  318 
  319 // For descriptions of the input parameters, see EncryptBufferXTS().
  320 void DecryptBufferXTS (unsigned __int8 *buffer,
  321                        TC_LARGEST_COMPILER_UINT length,
  322                        const UINT64_STRUCT *startDataUnitNo,
  323                        unsigned int startCipherBlockNo,
  324                        unsigned __int8 *ks,
  325                        unsigned __int8 *ks2,
  326                        int cipher)
  327 {
  328     if (CipherSupportsIntraDataUnitParallelization (cipher))
  329         DecryptBufferXTSParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
  330     else
  331         DecryptBufferXTSNonParallel (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher);
  332 }
  333 
  334 
  335 // Optimized for encryption algorithms supporting intra-data-unit parallelization
  336 static void DecryptBufferXTSParallel (unsigned __int8 *buffer,
  337                        TC_LARGEST_COMPILER_UINT length,
  338                        const UINT64_STRUCT *startDataUnitNo,
  339                        unsigned int startCipherBlockNo,
  340                        unsigned __int8 *ks,
  341                        unsigned __int8 *ks2,
  342                        int cipher)
  343 {
  344     unsigned __int8 finalCarry;
  345     unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
  346     unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
  347     unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
  348     unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
  349     unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  350     unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
  351     unsigned __int64 *dataUnitBufPtr;
  352     unsigned int startBlock = startCipherBlockNo, endBlock, block;
  353     unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
  354     TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
  355 
  356     // Convert the 64-bit data unit number into a little-endian 16-byte array.
  357     // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
  358     dataUnitNo = startDataUnitNo->Value;
  359     *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  360     *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
  361 
  362     if (length % BYTES_PER_XTS_BLOCK)
  363         TC_THROW_FATAL_EXCEPTION;
  364 
  365     blockCount = length / BYTES_PER_XTS_BLOCK;
  366 
  367     // Process all blocks in the buffer
  368     while (blockCount > 0)
  369     {
  370         if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  371             endBlock = startBlock + (unsigned int) blockCount;
  372         else
  373             endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  374 
  375         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  376         whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  377 
  378         // Encrypt the data unit number using the secondary key (in order to generate the first
  379         // whitening value for this data unit)
  380         *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
  381         *(whiteningValuePtr64 + 1) = 0;
  382         EncipherBlock (cipher, whiteningValue, ks2);
  383 
  384         // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
  385         // whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
  386         for (block = 0; block < endBlock; block++)
  387         {
  388             if (block >= startBlock)
  389             {
  390                 *whiteningValuesPtr64-- = *whiteningValuePtr64++;
  391                 *whiteningValuesPtr64-- = *whiteningValuePtr64;
  392             }
  393             else
  394                 whiteningValuePtr64++;
  395 
  396             // Derive the next whitening value
  397 
  398 #if BYTE_ORDER == LITTLE_ENDIAN
  399 
  400             // Little-endian platforms
  401 
  402             finalCarry =
  403                 (*whiteningValuePtr64 & 0x8000000000000000) ?
  404                 135 : 0;
  405 
  406             *whiteningValuePtr64-- <<= 1;
  407 
  408             if (*whiteningValuePtr64 & 0x8000000000000000)
  409                 *(whiteningValuePtr64 + 1) |= 1;
  410 
  411             *whiteningValuePtr64 <<= 1;
  412 
  413 #else
  414             // Big-endian platforms
  415 
  416             finalCarry =
  417                 (*whiteningValuePtr64 & 0x80) ?
  418                 135 : 0;
  419 
  420             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  421 
  422             whiteningValuePtr64--;
  423 
  424             if (*whiteningValuePtr64 & 0x80)
  425                 *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
  426 
  427             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  428 #endif
  429 
  430             whiteningValue[0] ^= finalCarry;
  431         }
  432 
  433         dataUnitBufPtr = bufPtr;
  434         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  435 
  436         // Decrypt blocks in this data unit
  437 
  438         for (block = startBlock; block < endBlock; block++)
  439         {
  440             *bufPtr++ ^= *whiteningValuesPtr64--;
  441             *bufPtr++ ^= *whiteningValuesPtr64--;
  442         }
  443 
  444         DecipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);
  445 
  446         bufPtr = dataUnitBufPtr;
  447         whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  448 
  449         for (block = startBlock; block < endBlock; block++)
  450         {
  451             *bufPtr++ ^= *whiteningValuesPtr64--;
  452             *bufPtr++ ^= *whiteningValuesPtr64--;
  453         }
  454 
  455         blockCount -= endBlock - startBlock;
  456         startBlock = 0;
  457         dataUnitNo++;
  458 
  459         *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  460     }
  461 
  462     FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  463     FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
  464 }
  465 
  466 
  467 // Optimized for encryption algorithms not supporting intra-data-unit parallelization
  468 static void DecryptBufferXTSNonParallel (unsigned __int8 *buffer,
  469                        TC_LARGEST_COMPILER_UINT length,
  470                        const UINT64_STRUCT *startDataUnitNo,
  471                        unsigned int startCipherBlockNo,
  472                        unsigned __int8 *ks,
  473                        unsigned __int8 *ks2,
  474                        int cipher)
  475 {
  476     unsigned __int8 finalCarry;
  477     unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
  478     unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
  479     unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  480     unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
  481     unsigned int startBlock = startCipherBlockNo, endBlock, block;
  482     TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
  483 
  484     // Convert the 64-bit data unit number into a little-endian 16-byte array.
  485     // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
  486     dataUnitNo = startDataUnitNo->Value;
  487     *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  488     *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
  489 
  490     if (length % BYTES_PER_XTS_BLOCK)
  491         TC_THROW_FATAL_EXCEPTION;
  492 
  493     blockCount = length / BYTES_PER_XTS_BLOCK;
  494 
  495     // Process all blocks in the buffer
  496     while (blockCount > 0)
  497     {
  498         if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  499             endBlock = startBlock + (unsigned int) blockCount;
  500         else
  501             endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  502 
  503         whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
  504 
  505         // Encrypt the data unit number using the secondary key (in order to generate the first
  506         // whitening value for this data unit)
  507         *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
  508         *(whiteningValuePtr64 + 1) = 0;
  509         EncipherBlock (cipher, whiteningValue, ks2);
  510 
  511         // Generate (and apply) subsequent whitening values for blocks in this data unit and
  512         // decrypt all relevant blocks in this data unit
  513         for (block = 0; block < endBlock; block++)
  514         {
  515             if (block >= startBlock)
  516             {
  517                 // Post-whitening
  518                 *bufPtr++ ^= *whiteningValuePtr64++;
  519                 *bufPtr-- ^= *whiteningValuePtr64--;
  520 
  521                 // Actual decryption
  522                 DecipherBlock (cipher, bufPtr, ks);
  523 
  524                 // Pre-whitening
  525                 *bufPtr++ ^= *whiteningValuePtr64++;
  526                 *bufPtr++ ^= *whiteningValuePtr64;
  527             }
  528             else
  529                 whiteningValuePtr64++;
  530 
  531             // Derive the next whitening value
  532 
  533 #if BYTE_ORDER == LITTLE_ENDIAN
  534 
  535             // Little-endian platforms
  536 
  537             finalCarry =
  538                 (*whiteningValuePtr64 & 0x8000000000000000) ?
  539                 135 : 0;
  540 
  541             *whiteningValuePtr64-- <<= 1;
  542 
  543             if (*whiteningValuePtr64 & 0x8000000000000000)
  544                 *(whiteningValuePtr64 + 1) |= 1;
  545 
  546             *whiteningValuePtr64 <<= 1;
  547 
  548 #else
  549             // Big-endian platforms
  550 
  551             finalCarry =
  552                 (*whiteningValuePtr64 & 0x80) ?
  553                 135 : 0;
  554 
  555             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  556 
  557             whiteningValuePtr64--;
  558 
  559             if (*whiteningValuePtr64 & 0x80)
  560                 *(whiteningValuePtr64 + 1) |= 0x0100000000000000;
  561 
  562             *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
  563 #endif
  564 
  565             whiteningValue[0] ^= finalCarry;
  566         }
  567 
  568         blockCount -= endBlock - startBlock;
  569         startBlock = 0;
  570         dataUnitNo++;
  571         *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
  572     }
  573 
  574     FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  575 }
  576 
  577 
  578 #else   // TC_NO_COMPILER_INT64
  579 
  580 /* ---- The following code is to be used only when native 64-bit data types are not available. ---- */
  581 
  582 #if BYTE_ORDER == BIG_ENDIAN
  583 #error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms
  584 #endif
  585 
  586 
  587 // Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit
  588 // environments/platforms) into a little-endian 16-byte array.
  589 static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32)
  590 {
  591     unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf;
  592 
  593     *bufPtr32++ = lowInt32;
  594     *bufPtr32++ = highInt32;
  595 
  596     // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes
  597     *bufPtr32++ = 0;
  598     *bufPtr32 = 0;
  599 }
  600 
  601 
  602 // Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters,
  603 // see the 64-bit version of EncryptBufferXTS().
  604 static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer,
  605                             TC_LARGEST_COMPILER_UINT length,
  606                             const UINT64_STRUCT *startDataUnitNo,
  607                             unsigned int startBlock,
  608                             unsigned __int8 *ks,
  609                             unsigned __int8 *ks2,
  610                             int cipher,
  611                             BOOL decryption)
  612 {
  613     TC_LARGEST_COMPILER_UINT blockCount;
  614     UINT64_STRUCT dataUnitNo;
  615     unsigned int block;
  616     unsigned int endBlock;
  617     unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
  618     unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
  619     unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer;
  620     unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
  621     unsigned __int8 finalCarry;
  622     unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1;
  623 
  624     // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms
  625     dataUnitNo.HighPart = startDataUnitNo->HighPart;
  626     dataUnitNo.LowPart = startDataUnitNo->LowPart;
  627 
  628     blockCount = length / BYTES_PER_XTS_BLOCK;
  629 
  630     // Convert the 64-bit data unit number into a little-endian 16-byte array.
  631     // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.)
  632     Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
  633 
  634     // Generate whitening values for all blocks in the buffer
  635     while (blockCount > 0)
  636     {
  637         if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  638             endBlock = startBlock + (unsigned int) blockCount;
  639         else
  640             endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  641 
  642         // Encrypt the data unit number using the secondary key (in order to generate the first
  643         // whitening value for this data unit)
  644         memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK);
  645         EncipherBlock (cipher, whiteningValue, ks2);
  646 
  647         // Generate (and apply) subsequent whitening values for blocks in this data unit and
  648         // encrypt/decrypt all relevant blocks in this data unit
  649         for (block = 0; block < endBlock; block++)
  650         {
  651             if (block >= startBlock)
  652             {
  653                 whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
  654 
  655                 // Whitening
  656                 *bufPtr32++ ^= *whiteningValuePtr32++;
  657                 *bufPtr32++ ^= *whiteningValuePtr32++;
  658                 *bufPtr32++ ^= *whiteningValuePtr32++;
  659                 *bufPtr32 ^= *whiteningValuePtr32;
  660 
  661                 bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1;
  662 
  663                 // Actual encryption/decryption
  664                 if (decryption)
  665                     DecipherBlock (cipher, bufPtr32, ks);
  666                 else
  667                     EncipherBlock (cipher, bufPtr32, ks);
  668 
  669                 whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
  670 
  671                 // Whitening
  672                 *bufPtr32++ ^= *whiteningValuePtr32++;
  673                 *bufPtr32++ ^= *whiteningValuePtr32++;
  674                 *bufPtr32++ ^= *whiteningValuePtr32++;
  675                 *bufPtr32++ ^= *whiteningValuePtr32;
  676             }
  677 
  678             // Derive the next whitening value
  679 
  680             finalCarry = 0;
  681 
  682             for (whiteningValuePtr32 = finalDwordWhiteningValuePtr;
  683                 whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue;
  684                 whiteningValuePtr32--)
  685             {
  686                 if (*whiteningValuePtr32 & 0x80000000)  // If the following shift results in a carry
  687                 {
  688                     if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word
  689                     {
  690                         // A regular carry
  691                         *(whiteningValuePtr32 + 1) |= 1;
  692                     }
  693                     else
  694                     {
  695                         // The highest byte shift will result in a carry
  696                         finalCarry = 135;
  697                     }
  698                 }
  699 
  700                 *whiteningValuePtr32 <<= 1;
  701             }
  702 
  703             whiteningValue[0] ^= finalCarry;
  704         }
  705 
  706         blockCount -= endBlock - startBlock;
  707         startBlock = 0;
  708 
  709         // Increase the data unit number by one
  710         if (!++dataUnitNo.LowPart)
  711         {
  712             dataUnitNo.HighPart++;
  713         }
  714 
  715         // Convert the 64-bit data unit number into a little-endian 16-byte array.
  716         Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
  717     }
  718 
  719     FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  720 }
  721 
  722 
  723 // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above.
  724 void EncryptBufferXTS (unsigned __int8 *buffer,
  725                        TC_LARGEST_COMPILER_UINT length,
  726                        const UINT64_STRUCT *startDataUnitNo,
  727                        unsigned int startCipherBlockNo,
  728                        unsigned __int8 *ks,
  729                        unsigned __int8 *ks2,
  730                        int cipher)
  731 {
  732     // Encrypt all plaintext blocks in the buffer
  733     EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE);
  734 }
  735 
  736 
  737 // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS().
  738 void DecryptBufferXTS (unsigned __int8 *buffer,
  739                        TC_LARGEST_COMPILER_UINT length,
  740                        const UINT64_STRUCT *startDataUnitNo,
  741                        unsigned int startCipherBlockNo,
  742                        unsigned __int8 *ks,
  743                        unsigned __int8 *ks2,
  744                        int cipher)
  745 {
  746     // Decrypt all ciphertext blocks in the buffer
  747     EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE);
  748 }
  749 
  750 #endif  // TC_NO_COMPILER_INT64