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

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