Annotation of truecrypt/volume/encryptionmodecbc.cpp, 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: #include "Platform/Memory.h"
                     10: #include "Common/Crc.h"
                     11: #include "Common/Endian.h"
                     12: #include "EncryptionModeCBC.h"
                     13: 
                     14: namespace TrueCrypt
                     15: {
                     16:        void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const
                     17:        {
                     18:                if_debug (ValidateState ());
                     19:                if_debug (ValidateParameters (data, length));
                     20: 
                     21:                if (IsOuterCBC (Ciphers))
                     22:                {
                     23:                        DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
                     24:                }
                     25:                else
                     26:                {
                     27:                        for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
                     28:                                iCipherList != Ciphers.rend();
                     29:                                ++iCipherList)
                     30:                        {
                     31:                                CipherList cl;
                     32:                                cl.push_back (*iCipherList);
                     33: 
                     34:                                DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
                     35:                        }
                     36:                }
                     37:        }
                     38: 
                     39:        void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
                     40:        {
                     41:                size_t blockSize = ciphers.front()->GetBlockSize();
                     42:                if (blockSize != 8 && blockSize != 16)
                     43:                        throw ParameterIncorrect (SRC_POS);
                     44: 
                     45:                uint32 *data32 = (uint32 *) data;
                     46:                uint32 bufIV[4];
                     47:                uint32 ct[4];
                     48:                uint64 i;
                     49: 
                     50:                bufIV[0] = iv[0];
                     51:                bufIV[1] = iv[1];
                     52:                if (blockSize == 16)
                     53:                {
                     54:                        bufIV[2] = iv[2];
                     55:                        bufIV[3] = iv[3];
                     56:                }
                     57: 
                     58:                for (i = 0; i < length / blockSize; i++)
                     59:                {
                     60:                        // Dewhitening
                     61:                        data32[0] ^= whitening[0];
                     62:                        data32[1] ^= whitening[1];
                     63:                        if (blockSize == 16)
                     64:                        {
                     65:                                data32[2] ^= whitening[0];
                     66:                                data32[3] ^= whitening[1];
                     67:                        }
                     68: 
                     69:                        // CBC
                     70:                        ct[0] = data32[0];
                     71:                        ct[1] = data32[1];
                     72:                        if (blockSize == 16)
                     73:                        {
                     74:                                ct[2] = data32[2];
                     75:                                ct[3] = data32[3];
                     76:                        }
                     77: 
                     78:                        for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin();
                     79:                                iCipherList != ciphers.rend();
                     80:                                ++iCipherList)
                     81:                        {
                     82:                                const Cipher &c = **iCipherList;
                     83: 
                     84:                                if (c.GetBlockSize () != blockSize)
                     85:                                        throw ParameterIncorrect (SRC_POS);
                     86: 
                     87:                                c.DecryptBlock ((byte *) data32);
                     88:                        }
                     89: 
                     90:                        // CBC
                     91:                        data32[0] ^= bufIV[0];
                     92:                        data32[1] ^= bufIV[1];
                     93:                        bufIV[0] = ct[0];
                     94:                        bufIV[1] = ct[1];
                     95:                        if (blockSize == 16)
                     96:                        {
                     97:                                data32[2] ^= bufIV[2];
                     98:                                data32[3] ^= bufIV[3];
                     99:                                bufIV[2] = ct[2];
                    100:                                bufIV[3] = ct[3];
                    101:                        }
                    102: 
                    103:                        data32 += blockSize / sizeof(*data32);
                    104:                }
                    105: 
                    106:                Memory::Erase (bufIV, sizeof (bufIV));
                    107:                Memory::Erase (ct, sizeof (ct));
                    108:        }
                    109: 
                    110:        void EncryptionModeCBC::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
                    111:        {
                    112:                if_debug (ValidateState ());
                    113:                if_debug (ValidateParameters (data, sectorCount, sectorSize));
                    114: 
                    115:                uint32 sectorIV[4];
                    116:                uint32 sectorWhitening[2];
                    117: 
                    118:                while (sectorCount--)
                    119:                {
                    120:                        if (IsOuterCBC (Ciphers))
                    121:                        {
                    122:                                InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
                    123:                                DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
                    124:                        }
                    125:                        else
                    126:                        {
                    127:                                for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
                    128:                                        iCipherList != Ciphers.rend();
                    129:                                        ++iCipherList)
                    130:                                {
                    131:                                        const Cipher &c = **iCipherList;
                    132:                                        CipherList cl;
                    133:                                        cl.push_back (*iCipherList);
                    134: 
                    135:                                        InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
                    136:                                        DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
                    137:                                }
                    138:                        }
                    139: 
                    140:                        data += sectorSize;
                    141:                        sectorIndex++;
                    142:                }
                    143: 
                    144:                Memory::Erase (sectorIV, sizeof (sectorIV));
                    145:                Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
                    146:        }
                    147: 
                    148:        void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const
                    149:        {
                    150:                if_debug (ValidateState ());
                    151:                if_debug (ValidateParameters (data, length));
                    152: 
                    153:                if (IsOuterCBC (Ciphers))
                    154:                {
                    155:                        EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
                    156:                }
                    157:                else
                    158:                {
                    159:                        for (CipherList::const_iterator iCipherList = Ciphers.begin();
                    160:                                iCipherList != Ciphers.end();
                    161:                                ++iCipherList)
                    162:                        {
                    163:                                CipherList cl;
                    164:                                cl.push_back (*iCipherList);
                    165: 
                    166:                                EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
                    167:                        }
                    168:                }
                    169:        }
                    170: 
                    171:        void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
                    172:        {
                    173:                size_t blockSize = ciphers.front()->GetBlockSize();
                    174:                if (blockSize != 8 && blockSize != 16)
                    175:                        throw ParameterIncorrect (SRC_POS);
                    176: 
                    177:                uint32 *data32 = (uint32 *) data;
                    178:                uint32 bufIV[4];
                    179:                uint64 i;
                    180: 
                    181:                bufIV[0] = iv[0];
                    182:                bufIV[1] = iv[1];
                    183:                if (blockSize == 16)
                    184:                {
                    185:                        bufIV[2] = iv[2];
                    186:                        bufIV[3] = iv[3];
                    187:                }
                    188: 
                    189:                for (i = 0; i < length / blockSize; i++)
                    190:                {
                    191:                        data32[0] ^= bufIV[0];
                    192:                        data32[1] ^= bufIV[1];
                    193:                        if (blockSize == 16)
                    194:                        {
                    195:                                data32[2] ^= bufIV[2];
                    196:                                data32[3] ^= bufIV[3];
                    197:                        }
                    198: 
                    199:                        for (CipherList::const_iterator iCipherList = ciphers.begin();
                    200:                                iCipherList != ciphers.end();
                    201:                                ++iCipherList)
                    202:                        {
                    203:                                const Cipher &c = **iCipherList;
                    204: 
                    205:                                if (c.GetBlockSize () != blockSize)
                    206:                                        throw ParameterIncorrect (SRC_POS);
                    207: 
                    208:                                c.EncryptBlock ((byte *) data32);
                    209:                        }
                    210: 
                    211:                        bufIV[0] = data32[0];
                    212:                        bufIV[1] = data32[1];
                    213:                        if (blockSize == 16)
                    214:                        {
                    215:                                bufIV[2] = data32[2];
                    216:                                bufIV[3] = data32[3];
                    217:                        }
                    218: 
                    219:                        data32[0] ^= whitening[0];
                    220:                        data32[1] ^= whitening[1];
                    221:                        if (blockSize == 16)
                    222:                        {
                    223:                                data32[2] ^= whitening[0];
                    224:                                data32[3] ^= whitening[1];
                    225:                        }
                    226: 
                    227:                        data32 += blockSize / sizeof(*data32);
                    228:                }
                    229: 
                    230:                Memory::Erase (bufIV, sizeof (bufIV));
                    231:        }
                    232: 
                    233:        void EncryptionModeCBC::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
                    234:        {
                    235:                if_debug (ValidateState ());
                    236:                if_debug (ValidateParameters (data, sectorCount, sectorSize));
                    237: 
                    238:                uint32 sectorIV[4];
                    239:                uint32 sectorWhitening[2];
                    240: 
                    241:                while (sectorCount--)
                    242:                {
                    243:                        if (IsOuterCBC (Ciphers))
                    244:                        {
                    245:                                InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
                    246:                                EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
                    247:                        }
                    248:                        else
                    249:                        {
                    250:                                for (CipherList::const_iterator iCipherList = Ciphers.begin();
                    251:                                        iCipherList != Ciphers.end();
                    252:                                        ++iCipherList)
                    253:                                {
                    254:                                        const Cipher &c = **iCipherList;
                    255:                                        CipherList cl;
                    256:                                        cl.push_back (*iCipherList);
                    257: 
                    258:                                        InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
                    259:                                        EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
                    260:                                }
                    261:                        }
                    262: 
                    263:                        data += sectorSize;
                    264:                        sectorIndex++;
                    265:                }
                    266: 
                    267:                Memory::Erase (sectorIV, sizeof (sectorIV));
                    268:                Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
                    269:        }
                    270: 
                    271:        void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const
                    272:        {
                    273:                if (blockSize != 8 && blockSize != 16)
                    274:                        throw ParameterIncorrect (SRC_POS);
                    275: 
                    276:                uint64 iv64[4];
                    277:                uint32 *iv32 = (uint32 *) iv64;
                    278: 
                    279:                iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex);
                    280:                iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex);
                    281:                iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex);
                    282:                if (blockSize == 16)
                    283:                {
                    284:                        iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex);
                    285:                }
                    286: 
                    287:                iv[0] = iv32[0];
                    288:                iv[1] = iv32[1];
                    289: 
                    290:                if (blockSize == 8)
                    291:                {
                    292:                        whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) );
                    293:                        whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) );
                    294:                }
                    295:                else
                    296:                {
                    297:                        iv[2] = iv32[2];
                    298:                        iv[3] = iv32[3];
                    299: 
                    300:                        whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) );
                    301:                        whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) );
                    302:                }
                    303:        }
                    304: 
                    305:        bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const
                    306:        {
                    307:                if (ciphers.size() < 2)
                    308:                        return false;
                    309: 
                    310:                size_t blockSize = ciphers.front()->GetBlockSize();
                    311: 
                    312:                for (CipherList::const_iterator iCipherList = ciphers.begin();
                    313:                        iCipherList != ciphers.end();
                    314:                        ++iCipherList)
                    315:                {
                    316:                        const Cipher &c = **iCipherList;
                    317:                        if (c.GetBlockSize() != blockSize)
                    318:                                return false;
                    319:                }
                    320: 
                    321:                return true;
                    322:        }
                    323: 
                    324:        void EncryptionModeCBC::SetKey (const ConstBufferPtr &key)
                    325:        {
                    326:                if (key.Size() != GetKeySize ())
                    327:                        throw ParameterIncorrect (SRC_POS);
                    328: 
                    329:                if (!KeySet)
                    330:                        IV.Allocate (GetKeySize ());
                    331:                
                    332:                IV.CopyFrom (key);
                    333:                KeySet = true;
                    334:        }
                    335: }

unix.superglobalmegacorp.com

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