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

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