"Fossies" - the Fresh Open Source Software Archive

Member "src/Volume/EncryptionModeXTS.cpp" (10 Oct 2018, 11801 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 "EncryptionModeXTS.cpp" see the Fossies "Dox" file reference documentation.

    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 #include "EncryptionModeXTS.h"
   14 #include "Common/Crypto.h"
   15 
   16 namespace VeraCrypt
   17 {
   18     void EncryptionModeXTS::Encrypt (byte *data, uint64 length) const
   19     {
   20         EncryptBuffer (data, length, 0);
   21     }
   22 
   23     void EncryptionModeXTS::EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const
   24     {
   25         if_debug (ValidateState());
   26 
   27         CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.begin();
   28 
   29         for (CipherList::const_iterator iCipher = Ciphers.begin(); iCipher != Ciphers.end(); ++iCipher)
   30         {
   31             EncryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0);
   32             ++iSecondaryCipher;
   33         }
   34 
   35         assert (iSecondaryCipher == SecondaryCiphers.end());
   36     }
   37 
   38     void EncryptionModeXTS::EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const
   39     {
   40         byte finalCarry;
   41         byte whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
   42         byte whiteningValue [BYTES_PER_XTS_BLOCK];
   43         byte byteBufUnitNo [BYTES_PER_XTS_BLOCK];
   44         uint64 *whiteningValuesPtr64 = (uint64 *) whiteningValues;
   45         uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue;
   46         uint64 *bufPtr = (uint64 *) buffer;
   47         uint64 *dataUnitBufPtr;
   48         unsigned int startBlock = startCipherBlockNo, endBlock, block;
   49         uint64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
   50         uint64 blockCount, dataUnitNo;
   51 
   52         startDataUnitNo += SectorOffset;
   53 
   54         /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
   55         finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
   56         number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
   57         as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
   58         the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
   59         derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
   60 
   61         // Convert the 64-bit data unit number into a little-endian 16-byte array.
   62         // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
   63         dataUnitNo = startDataUnitNo;
   64         *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
   65         *((uint64 *) byteBufUnitNo + 1) = 0;
   66 
   67         if (length % BYTES_PER_XTS_BLOCK)
   68             TC_THROW_FATAL_EXCEPTION;
   69 
   70         blockCount = length / BYTES_PER_XTS_BLOCK;
   71 
   72         // Process all blocks in the buffer
   73         while (blockCount > 0)
   74         {
   75             if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
   76                 endBlock = startBlock + (unsigned int) blockCount;
   77             else
   78                 endBlock = BLOCKS_PER_XTS_DATA_UNIT;
   79 
   80             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
   81             whiteningValuePtr64 = (uint64 *) whiteningValue;
   82 
   83             // Encrypt the data unit number using the secondary key (in order to generate the first
   84             // whitening value for this data unit)
   85             *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo);
   86             *(whiteningValuePtr64 + 1) = 0;
   87             secondaryCipher.EncryptBlock (whiteningValue);
   88 
   89             // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
   90             // whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
   91             for (block = 0; block < endBlock; block++)
   92             {
   93                 if (block >= startBlock)
   94                 {
   95                     *whiteningValuesPtr64-- = *whiteningValuePtr64++;
   96                     *whiteningValuesPtr64-- = *whiteningValuePtr64;
   97                 }
   98                 else
   99                     whiteningValuePtr64++;
  100 
  101                 // Derive the next whitening value
  102 
  103 #if BYTE_ORDER == LITTLE_ENDIAN
  104 
  105                 // Little-endian platforms
  106 
  107                 finalCarry =
  108                     (*whiteningValuePtr64 & 0x8000000000000000ULL) ?
  109                     135 : 0;
  110 
  111                 *whiteningValuePtr64-- <<= 1;
  112 
  113                 if (*whiteningValuePtr64 & 0x8000000000000000ULL)
  114                     *(whiteningValuePtr64 + 1) |= 1;
  115 
  116                 *whiteningValuePtr64 <<= 1;
  117 #else
  118 
  119                 // Big-endian platforms
  120 
  121                 finalCarry =
  122                     (*whiteningValuePtr64 & 0x80) ?
  123                     135 : 0;
  124 
  125                 *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
  126 
  127                 whiteningValuePtr64--;
  128 
  129                 if (*whiteningValuePtr64 & 0x80)
  130                     *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL;
  131 
  132                 *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
  133 #endif
  134 
  135                 whiteningValue[0] ^= finalCarry;
  136             }
  137 
  138             dataUnitBufPtr = bufPtr;
  139             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  140 
  141             // Encrypt all blocks in this data unit
  142 
  143             for (block = startBlock; block < endBlock; block++)
  144             {
  145                 // Pre-whitening
  146                 *bufPtr++ ^= *whiteningValuesPtr64--;
  147                 *bufPtr++ ^= *whiteningValuesPtr64--;
  148             }
  149 
  150             // Actual encryption
  151             cipher.EncryptBlocks ((byte *) dataUnitBufPtr, endBlock - startBlock);
  152 
  153             bufPtr = dataUnitBufPtr;
  154             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  155 
  156             for (block = startBlock; block < endBlock; block++)
  157             {
  158                 // Post-whitening
  159                 *bufPtr++ ^= *whiteningValuesPtr64--;
  160                 *bufPtr++ ^= *whiteningValuesPtr64--;
  161             }
  162 
  163             blockCount -= endBlock - startBlock;
  164             startBlock = 0;
  165             dataUnitNo++;
  166             *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
  167         }
  168 
  169         FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  170         FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
  171     }
  172 
  173     void EncryptionModeXTS::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
  174     {
  175         EncryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE);
  176     }
  177 
  178     size_t EncryptionModeXTS::GetKeySize () const
  179     {
  180         if (Ciphers.empty())
  181             throw NotInitialized (SRC_POS);
  182 
  183         size_t keySize = 0;
  184         foreach_ref (const Cipher &cipher, SecondaryCiphers)
  185         {
  186             keySize += cipher.GetKeySize();
  187         }
  188 
  189         return keySize;
  190     }
  191 
  192     void EncryptionModeXTS::Decrypt (byte *data, uint64 length) const
  193     {
  194         DecryptBuffer (data, length, 0);
  195     }
  196 
  197     void EncryptionModeXTS::DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const
  198     {
  199         if_debug (ValidateState());
  200 
  201         CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.end();
  202 
  203         for (CipherList::const_reverse_iterator iCipher = Ciphers.rbegin(); iCipher != Ciphers.rend(); ++iCipher)
  204         {
  205             --iSecondaryCipher;
  206             DecryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0);
  207         }
  208 
  209         assert (iSecondaryCipher == SecondaryCiphers.begin());
  210     }
  211 
  212     void EncryptionModeXTS::DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const
  213     {
  214         byte finalCarry;
  215         byte whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
  216         byte whiteningValue [BYTES_PER_XTS_BLOCK];
  217         byte byteBufUnitNo [BYTES_PER_XTS_BLOCK];
  218         uint64 *whiteningValuesPtr64 = (uint64 *) whiteningValues;
  219         uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue;
  220         uint64 *bufPtr = (uint64 *) buffer;
  221         uint64 *dataUnitBufPtr;
  222         unsigned int startBlock = startCipherBlockNo, endBlock, block;
  223         uint64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
  224         uint64 blockCount, dataUnitNo;
  225 
  226         startDataUnitNo += SectorOffset;
  227 
  228         // Convert the 64-bit data unit number into a little-endian 16-byte array.
  229         // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
  230         dataUnitNo = startDataUnitNo;
  231         *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
  232         *((uint64 *) byteBufUnitNo + 1) = 0;
  233 
  234         if (length % BYTES_PER_XTS_BLOCK)
  235             TC_THROW_FATAL_EXCEPTION;
  236 
  237         blockCount = length / BYTES_PER_XTS_BLOCK;
  238 
  239         // Process all blocks in the buffer
  240         while (blockCount > 0)
  241         {
  242             if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
  243                 endBlock = startBlock + (unsigned int) blockCount;
  244             else
  245                 endBlock = BLOCKS_PER_XTS_DATA_UNIT;
  246 
  247             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  248             whiteningValuePtr64 = (uint64 *) whiteningValue;
  249 
  250             // Encrypt the data unit number using the secondary key (in order to generate the first
  251             // whitening value for this data unit)
  252             *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo);
  253             *(whiteningValuePtr64 + 1) = 0;
  254             secondaryCipher.EncryptBlock (whiteningValue);
  255 
  256             // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
  257             // whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
  258             for (block = 0; block < endBlock; block++)
  259             {
  260                 if (block >= startBlock)
  261                 {
  262                     *whiteningValuesPtr64-- = *whiteningValuePtr64++;
  263                     *whiteningValuesPtr64-- = *whiteningValuePtr64;
  264                 }
  265                 else
  266                     whiteningValuePtr64++;
  267 
  268                 // Derive the next whitening value
  269 
  270 #if BYTE_ORDER == LITTLE_ENDIAN
  271 
  272                 // Little-endian platforms
  273 
  274                 finalCarry =
  275                     (*whiteningValuePtr64 & 0x8000000000000000ULL) ?
  276                     135 : 0;
  277 
  278                 *whiteningValuePtr64-- <<= 1;
  279 
  280                 if (*whiteningValuePtr64 & 0x8000000000000000ULL)
  281                     *(whiteningValuePtr64 + 1) |= 1;
  282 
  283                 *whiteningValuePtr64 <<= 1;
  284 
  285 #else
  286                 // Big-endian platforms
  287 
  288                 finalCarry =
  289                     (*whiteningValuePtr64 & 0x80) ?
  290                     135 : 0;
  291 
  292                 *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
  293 
  294                 whiteningValuePtr64--;
  295 
  296                 if (*whiteningValuePtr64 & 0x80)
  297                     *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL;
  298 
  299                 *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
  300 #endif
  301 
  302                 whiteningValue[0] ^= finalCarry;
  303             }
  304 
  305             dataUnitBufPtr = bufPtr;
  306             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  307 
  308             // Decrypt blocks in this data unit
  309 
  310             for (block = startBlock; block < endBlock; block++)
  311             {
  312                 *bufPtr++ ^= *whiteningValuesPtr64--;
  313                 *bufPtr++ ^= *whiteningValuesPtr64--;
  314             }
  315 
  316             cipher.DecryptBlocks ((byte *) dataUnitBufPtr, endBlock - startBlock);
  317 
  318             bufPtr = dataUnitBufPtr;
  319             whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
  320 
  321             for (block = startBlock; block < endBlock; block++)
  322             {
  323                 *bufPtr++ ^= *whiteningValuesPtr64--;
  324                 *bufPtr++ ^= *whiteningValuesPtr64--;
  325             }
  326 
  327             blockCount -= endBlock - startBlock;
  328             startBlock = 0;
  329             dataUnitNo++;
  330 
  331             *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
  332         }
  333 
  334         FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
  335         FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
  336     }
  337 
  338     void EncryptionModeXTS::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
  339     {
  340         DecryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE);
  341     }
  342 
  343     void EncryptionModeXTS::SetCiphers (const CipherList &ciphers)
  344     {
  345         EncryptionMode::SetCiphers (ciphers);
  346 
  347         SecondaryCiphers.clear();
  348 
  349         foreach_ref (const Cipher &cipher, ciphers)
  350         {
  351             SecondaryCiphers.push_back (cipher.GetNew());
  352         }
  353 
  354         if (SecondaryKey.Size() > 0)
  355             SetSecondaryCipherKeys();
  356     }
  357 
  358     void EncryptionModeXTS::SetKey (const ConstBufferPtr &key)
  359     {
  360         SecondaryKey.Allocate (key.Size());
  361         SecondaryKey.CopyFrom (key);
  362 
  363         if (!SecondaryCiphers.empty())
  364             SetSecondaryCipherKeys();
  365     }
  366 
  367     void EncryptionModeXTS::SetSecondaryCipherKeys ()
  368     {
  369         size_t keyOffset = 0;
  370         foreach_ref (Cipher &cipher, SecondaryCiphers)
  371         {
  372             cipher.SetKey (SecondaryKey.GetRange (keyOffset, cipher.GetKeySize()));
  373             keyOffset += cipher.GetKeySize();
  374         }
  375 
  376         KeySet = true;
  377     }
  378 }