Annotation of truecrypt/common/xts.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.