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

1.1       root        1: /*
                      2:  Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
                      3: 
1.1.1.6 ! root        4:  Governed by the TrueCrypt License 2.8 the full text of which is contained
1.1       root        5:  in the file License.txt included in TrueCrypt binary and source code
                      6:  distribution packages.
                      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: {
                     49:        unsigned __int8 finalCarry;
                     50:        unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
                     51:        unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
                     52:        unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
                     53:        unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
                     54:        unsigned int startBlock = startCipherBlockNo, endBlock, block;
                     55:        TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
                     56: 
                     57:        /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
                     58:        finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
                     59:        number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
                     60:        as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
                     61:        the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
                     62:        derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
                     63: 
                     64:        // Convert the 64-bit data unit number into a little-endian 16-byte array. 
                     65:        // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
                     66:        dataUnitNo = startDataUnitNo->Value;
                     67:        *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
                     68:        *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
                     69: 
                     70:        if (length % BYTES_PER_XTS_BLOCK)
                     71:                TC_THROW_FATAL_EXCEPTION;
                     72: 
                     73:        blockCount = length / BYTES_PER_XTS_BLOCK;
                     74: 
                     75:        // Process all blocks in the buffer
                     76:        while (blockCount > 0)
                     77:        {
                     78:                if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
                     79:                        endBlock = startBlock + (unsigned int) blockCount;
                     80:                else
                     81:                        endBlock = BLOCKS_PER_XTS_DATA_UNIT;
                     82: 
                     83:                whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
                     84: 
                     85:                // Encrypt the data unit number using the secondary key (in order to generate the first 
                     86:                // whitening value for this data unit)
                     87:                *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
                     88:                *(whiteningValuePtr64 + 1) = 0;
                     89:                EncipherBlock (cipher, whiteningValue, ks2);
                     90: 
1.1.1.3   root       91:                // Generate (and apply) subsequent whitening values for blocks in this data unit and
                     92:                // encrypt all relevant blocks in this data unit
1.1       root       93:                for (block = 0; block < endBlock; block++)
                     94:                {
                     95:                        if (block >= startBlock)
                     96:                        {
1.1.1.3   root       97:                                // Pre-whitening
                     98:                                *bufPtr++ ^= *whiteningValuePtr64++;
                     99:                                *bufPtr-- ^= *whiteningValuePtr64--;
                    100: 
                    101:                                // Actual encryption
                    102:                                EncipherBlock (cipher, bufPtr, ks);
                    103: 
                    104:                                // Post-whitening
                    105:                                *bufPtr++ ^= *whiteningValuePtr64++;
                    106:                                *bufPtr++ ^= *whiteningValuePtr64;
1.1       root      107:                        }
                    108:                        else
                    109:                                whiteningValuePtr64++;
                    110: 
                    111:                        // Derive the next whitening value
                    112: 
                    113: #if BYTE_ORDER == LITTLE_ENDIAN
                    114: 
1.1.1.3   root      115:                        // Little-endian platforms
1.1       root      116: 
                    117:                        finalCarry = 
                    118:                                (*whiteningValuePtr64 & 0x8000000000000000) ?
                    119:                                135 : 0;
                    120: 
                    121:                        *whiteningValuePtr64-- <<= 1;
                    122: 
                    123:                        if (*whiteningValuePtr64 & 0x8000000000000000)
                    124:                                *(whiteningValuePtr64 + 1) |= 1;        
                    125: 
                    126:                        *whiteningValuePtr64 <<= 1;
                    127: #else
1.1.1.3   root      128: 
                    129:                        // Big-endian platforms
1.1       root      130: 
                    131:                        finalCarry = 
                    132:                                (*whiteningValuePtr64 & 0x80) ?
                    133:                                135 : 0;
                    134: 
                    135:                        *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
                    136: 
                    137:                        whiteningValuePtr64--;
                    138: 
                    139:                        if (*whiteningValuePtr64 & 0x80)
                    140:                                *(whiteningValuePtr64 + 1) |= 0x0100000000000000;       
                    141: 
                    142:                        *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
                    143: #endif
                    144: 
                    145:                        whiteningValue[0] ^= finalCarry;
                    146:                }
                    147: 
1.1.1.3   root      148:                blockCount -= endBlock - startBlock;
1.1       root      149:                startBlock = 0;
                    150:                dataUnitNo++;
                    151:                *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
                    152:        }
                    153: 
1.1.1.3   root      154:        FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1       root      155: }
                    156: 
                    157: 
                    158: // For descriptions of the input parameters, see EncryptBufferXTS().
                    159: void DecryptBufferXTS (unsigned __int8 *buffer,
                    160:                                           TC_LARGEST_COMPILER_UINT length,
                    161:                                           const UINT64_STRUCT *startDataUnitNo,
                    162:                                           unsigned int startCipherBlockNo,
                    163:                                           unsigned __int8 *ks,
                    164:                                           unsigned __int8 *ks2,
                    165:                                           int cipher)
                    166: {
                    167:        unsigned __int8 finalCarry;
                    168:        unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
                    169:        unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
                    170:        unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
                    171:        unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
                    172:        unsigned int startBlock = startCipherBlockNo, endBlock, block;
                    173:        TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
1.1.1.3   root      174: 
1.1       root      175:        // Convert the 64-bit data unit number into a little-endian 16-byte array. 
                    176:        // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
                    177:        dataUnitNo = startDataUnitNo->Value;
                    178:        *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
                    179:        *((unsigned __int64 *) byteBufUnitNo + 1) = 0;
                    180: 
                    181:        if (length % BYTES_PER_XTS_BLOCK)
                    182:                TC_THROW_FATAL_EXCEPTION;
                    183: 
                    184:        blockCount = length / BYTES_PER_XTS_BLOCK;
                    185: 
                    186:        // Process all blocks in the buffer
                    187:        while (blockCount > 0)
                    188:        {
                    189:                if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
                    190:                        endBlock = startBlock + (unsigned int) blockCount;
                    191:                else
                    192:                        endBlock = BLOCKS_PER_XTS_DATA_UNIT;
                    193: 
                    194:                whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
                    195: 
                    196:                // Encrypt the data unit number using the secondary key (in order to generate the first 
                    197:                // whitening value for this data unit)
                    198:                *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
                    199:                *(whiteningValuePtr64 + 1) = 0;
                    200:                EncipherBlock (cipher, whiteningValue, ks2);
                    201: 
1.1.1.3   root      202:                // Generate (and apply) subsequent whitening values for blocks in this data unit and
                    203:                // decrypt all relevant blocks in this data unit
1.1       root      204:                for (block = 0; block < endBlock; block++)
                    205:                {
                    206:                        if (block >= startBlock)
                    207:                        {
1.1.1.3   root      208:                                // Post-whitening
                    209:                                *bufPtr++ ^= *whiteningValuePtr64++;
                    210:                                *bufPtr-- ^= *whiteningValuePtr64--;
                    211: 
                    212:                                // Actual decryption
                    213:                                DecipherBlock (cipher, bufPtr, ks);
                    214: 
                    215:                                // Pre-whitening
                    216:                                *bufPtr++ ^= *whiteningValuePtr64++;
                    217:                                *bufPtr++ ^= *whiteningValuePtr64;
1.1       root      218:                        }
                    219:                        else
                    220:                                whiteningValuePtr64++;
                    221: 
                    222:                        // Derive the next whitening value
                    223: 
                    224: #if BYTE_ORDER == LITTLE_ENDIAN
                    225: 
1.1.1.3   root      226:                        // Little-endian platforms
1.1       root      227: 
                    228:                        finalCarry = 
                    229:                                (*whiteningValuePtr64 & 0x8000000000000000) ?
                    230:                                135 : 0;
                    231: 
                    232:                        *whiteningValuePtr64-- <<= 1;
                    233: 
                    234:                        if (*whiteningValuePtr64 & 0x8000000000000000)
                    235:                                *(whiteningValuePtr64 + 1) |= 1;        
                    236: 
                    237:                        *whiteningValuePtr64 <<= 1;
                    238: 
                    239: #else
1.1.1.3   root      240:                        // Big-endian platforms
1.1       root      241: 
                    242:                        finalCarry = 
                    243:                                (*whiteningValuePtr64 & 0x80) ?
                    244:                                135 : 0;
                    245: 
                    246:                        *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
                    247: 
                    248:                        whiteningValuePtr64--;
                    249: 
                    250:                        if (*whiteningValuePtr64 & 0x80)
                    251:                                *(whiteningValuePtr64 + 1) |= 0x0100000000000000;       
                    252: 
                    253:                        *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
                    254: #endif
                    255: 
                    256:                        whiteningValue[0] ^= finalCarry;
                    257:                }
                    258: 
1.1.1.3   root      259:                blockCount -= endBlock - startBlock;
1.1       root      260:                startBlock = 0;
                    261:                dataUnitNo++;
                    262:                *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
                    263:        }
                    264: 
1.1.1.3   root      265:        FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1       root      266: }
                    267: 
                    268: 
                    269: 
1.1.1.3   root      270: #else  // TC_NO_COMPILER_INT64
1.1       root      271: 
1.1.1.3   root      272: /* ---- The following code is to be used only when native 64-bit data types are not available. ---- */
1.1       root      273: 
                    274: #if BYTE_ORDER == BIG_ENDIAN
1.1.1.3   root      275: #error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms
1.1       root      276: #endif 
                    277: 
                    278: 
                    279: // Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit
                    280: // environments/platforms) into a little-endian 16-byte array.
                    281: static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32)
                    282: {
                    283:        unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf;
                    284: 
                    285:        *bufPtr32++ = lowInt32;
                    286:        *bufPtr32++ = highInt32;
                    287: 
                    288:        // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes
                    289:        *bufPtr32++ = 0;
                    290:        *bufPtr32 = 0;
                    291: }
                    292: 
                    293: 
1.1.1.3   root      294: // Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters,
                    295: // see the 64-bit version of EncryptBufferXTS().
                    296: static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer,
1.1       root      297:                                                        TC_LARGEST_COMPILER_UINT length,
                    298:                                                        const UINT64_STRUCT *startDataUnitNo,
                    299:                                                        unsigned int startBlock,
1.1.1.3   root      300:                                                        unsigned __int8 *ks,
1.1       root      301:                                                        unsigned __int8 *ks2,
1.1.1.3   root      302:                                                        int cipher,
                    303:                                                        BOOL decryption)
1.1       root      304: {
                    305:        TC_LARGEST_COMPILER_UINT blockCount;
                    306:        UINT64_STRUCT dataUnitNo;
                    307:        unsigned int block;
                    308:        unsigned int endBlock;
                    309:        unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
                    310:        unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
                    311:        unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer;
                    312:        unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
                    313:        unsigned __int8 finalCarry;
                    314:        unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1;
                    315: 
                    316:        // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms
                    317:        dataUnitNo.HighPart = startDataUnitNo->HighPart;
                    318:        dataUnitNo.LowPart = startDataUnitNo->LowPart;
                    319: 
                    320:        blockCount = length / BYTES_PER_XTS_BLOCK;
                    321: 
                    322:        // Convert the 64-bit data unit number into a little-endian 16-byte array. 
                    323:        // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.)
                    324:        Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
                    325: 
                    326:        // Generate whitening values for all blocks in the buffer
                    327:        while (blockCount > 0)
                    328:        {
                    329:                if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
                    330:                        endBlock = startBlock + (unsigned int) blockCount;
                    331:                else
                    332:                        endBlock = BLOCKS_PER_XTS_DATA_UNIT;
                    333: 
                    334:                // Encrypt the data unit number using the secondary key (in order to generate the first 
                    335:                // whitening value for this data unit)
                    336:                memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK);
                    337:                EncipherBlock (cipher, whiteningValue, ks2);
                    338: 
1.1.1.3   root      339:                // Generate (and apply) subsequent whitening values for blocks in this data unit and
                    340:                // encrypt/decrypt all relevant blocks in this data unit
1.1       root      341:                for (block = 0; block < endBlock; block++)
                    342:                {
                    343:                        if (block >= startBlock)
                    344:                        {
                    345:                                whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
                    346: 
1.1.1.3   root      347:                                // Whitening
1.1       root      348:                                *bufPtr32++ ^= *whiteningValuePtr32++;
                    349:                                *bufPtr32++ ^= *whiteningValuePtr32++;
                    350:                                *bufPtr32++ ^= *whiteningValuePtr32++;
1.1.1.3   root      351:                                *bufPtr32 ^= *whiteningValuePtr32;
                    352: 
                    353:                                bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1;
                    354: 
                    355:                                // Actual encryption/decryption
                    356:                                if (decryption)
                    357:                                        DecipherBlock (cipher, bufPtr32, ks);
                    358:                                else
                    359:                                        EncipherBlock (cipher, bufPtr32, ks);
                    360: 
                    361:                                whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
1.1       root      362: 
1.1.1.3   root      363:                                // Whitening
                    364:                                *bufPtr32++ ^= *whiteningValuePtr32++;
                    365:                                *bufPtr32++ ^= *whiteningValuePtr32++;
                    366:                                *bufPtr32++ ^= *whiteningValuePtr32++;
                    367:                                *bufPtr32++ ^= *whiteningValuePtr32;
1.1       root      368:                        }
                    369: 
                    370:                        // Derive the next whitening value
                    371: 
                    372:                        finalCarry = 0;
                    373: 
                    374:                        for (whiteningValuePtr32 = finalDwordWhiteningValuePtr;
                    375:                                whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue;
                    376:                                whiteningValuePtr32--)
                    377:                        {
                    378:                                if (*whiteningValuePtr32 & 0x80000000)  // If the following shift results in a carry
                    379:                                {
                    380:                                        if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word
                    381:                                        {
                    382:                                                // A regular carry
                    383:                                                *(whiteningValuePtr32 + 1) |= 1;
                    384:                                        }
                    385:                                        else 
                    386:                                        {
                    387:                                                // The highest byte shift will result in a carry
                    388:                                                finalCarry = 135;
                    389:                                        }
                    390:                                }
                    391: 
                    392:                                *whiteningValuePtr32 <<= 1;
                    393:                        }
                    394: 
                    395:                        whiteningValue[0] ^= finalCarry;
                    396:                }
                    397: 
1.1.1.3   root      398:                blockCount -= endBlock - startBlock;
1.1       root      399:                startBlock = 0;
                    400: 
                    401:                // Increase the data unit number by one
1.1.1.3   root      402:                if (!++dataUnitNo.LowPart)
                    403:                {
                    404:                        dataUnitNo.HighPart++;
                    405:                }
1.1       root      406: 
                    407:                // Convert the 64-bit data unit number into a little-endian 16-byte array. 
                    408:                Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
                    409:        }
                    410: 
1.1.1.3   root      411:        FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
1.1       root      412: }
                    413: 
                    414: 
1.1.1.3   root      415: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above.
1.1       root      416: void EncryptBufferXTS (unsigned __int8 *buffer,
                    417:                                           TC_LARGEST_COMPILER_UINT length,
1.1.1.3   root      418:                                           const UINT64_STRUCT *startDataUnitNo,
1.1       root      419:                                           unsigned int startCipherBlockNo,
                    420:                                           unsigned __int8 *ks,
                    421:                                           unsigned __int8 *ks2,
                    422:                                           int cipher)
                    423: {
                    424:        // Encrypt all plaintext blocks in the buffer
1.1.1.3   root      425:        EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE);
1.1       root      426: }
                    427: 
                    428: 
1.1.1.3   root      429: // For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS().
1.1       root      430: void DecryptBufferXTS (unsigned __int8 *buffer,
                    431:                                           TC_LARGEST_COMPILER_UINT length,
1.1.1.3   root      432:                                           const UINT64_STRUCT *startDataUnitNo,
1.1       root      433:                                           unsigned int startCipherBlockNo,
                    434:                                           unsigned __int8 *ks,
                    435:                                           unsigned __int8 *ks2,
                    436:                                           int cipher)
                    437: {
1.1.1.3   root      438:        // Decrypt all ciphertext blocks in the buffer
                    439:        EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE);
1.1       root      440: }
                    441: 
1.1.1.3   root      442: #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.