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

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

unix.superglobalmegacorp.com

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