diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2014-05-31 18:44:53 +0200 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2014-11-08 23:18:59 +0100 |
commit | 7ffce028d04a6b13ef762e2b89c34b688e8ca59d (patch) | |
tree | eefedb6e94de5b26fa963675969490c641c29077 /src/Volume/EncryptionModeCBC.cpp | |
parent | 97011f179cfd3dcd12446ef4ccb6964c8e52c3db (diff) | |
download | VeraCrypt-7ffce028d04a6b13ef762e2b89c34b688e8ca59d.tar.gz VeraCrypt-7ffce028d04a6b13ef762e2b89c34b688e8ca59d.zip |
Add TrueCrypt 7.1a MacOSX/Linux specific source files.
Diffstat (limited to 'src/Volume/EncryptionModeCBC.cpp')
-rw-r--r-- | src/Volume/EncryptionModeCBC.cpp | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/Volume/EncryptionModeCBC.cpp b/src/Volume/EncryptionModeCBC.cpp new file mode 100644 index 00000000..f299b888 --- /dev/null +++ b/src/Volume/EncryptionModeCBC.cpp @@ -0,0 +1,335 @@ +/* + Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved. + + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. +*/ + +#include "Platform/Memory.h" +#include "Common/Crc.h" +#include "Common/Endian.h" +#include "EncryptionModeCBC.h" + +namespace TrueCrypt +{ + void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, length)); + + if (IsOuterCBC (Ciphers)) + { + DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + else + { + for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); + iCipherList != Ciphers.rend(); + ++iCipherList) + { + CipherList cl; + cl.push_back (*iCipherList); + + DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + } + } + + void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const + { + size_t blockSize = ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint32 *data32 = (uint32 *) data; + uint32 bufIV[4]; + uint32 ct[4]; + uint64 i; + + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + for (i = 0; i < length / blockSize; i++) + { + // Dewhitening + data32[0] ^= whitening[0]; + data32[1] ^= whitening[1]; + if (blockSize == 16) + { + data32[2] ^= whitening[0]; + data32[3] ^= whitening[1]; + } + + // CBC + ct[0] = data32[0]; + ct[1] = data32[1]; + if (blockSize == 16) + { + ct[2] = data32[2]; + ct[3] = data32[3]; + } + + for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin(); + iCipherList != ciphers.rend(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.DecryptBlock ((byte *) data32); + } + + // CBC + data32[0] ^= bufIV[0]; + data32[1] ^= bufIV[1]; + bufIV[0] = ct[0]; + bufIV[1] = ct[1]; + if (blockSize == 16) + { + data32[2] ^= bufIV[2]; + data32[3] ^= bufIV[3]; + bufIV[2] = ct[2]; + bufIV[3] = ct[3]; + } + + data32 += blockSize / sizeof(*data32); + } + + Memory::Erase (bufIV, sizeof (bufIV)); + Memory::Erase (ct, sizeof (ct)); + } + + void EncryptionModeCBC::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + uint32 sectorIV[4]; + uint32 sectorWhitening[2]; + + while (sectorCount--) + { + if (IsOuterCBC (Ciphers)) + { + InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); + } + else + { + for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); + iCipherList != Ciphers.rend(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + CipherList cl; + cl.push_back (*iCipherList); + + InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); + } + } + + data += sectorSize; + sectorIndex++; + } + + Memory::Erase (sectorIV, sizeof (sectorIV)); + Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); + } + + void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, length)); + + if (IsOuterCBC (Ciphers)) + { + EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + else + { + for (CipherList::const_iterator iCipherList = Ciphers.begin(); + iCipherList != Ciphers.end(); + ++iCipherList) + { + CipherList cl; + cl.push_back (*iCipherList); + + EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + } + } + + void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const + { + size_t blockSize = ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint32 *data32 = (uint32 *) data; + uint32 bufIV[4]; + uint64 i; + + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + for (i = 0; i < length / blockSize; i++) + { + data32[0] ^= bufIV[0]; + data32[1] ^= bufIV[1]; + if (blockSize == 16) + { + data32[2] ^= bufIV[2]; + data32[3] ^= bufIV[3]; + } + + for (CipherList::const_iterator iCipherList = ciphers.begin(); + iCipherList != ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.EncryptBlock ((byte *) data32); + } + + bufIV[0] = data32[0]; + bufIV[1] = data32[1]; + if (blockSize == 16) + { + bufIV[2] = data32[2]; + bufIV[3] = data32[3]; + } + + data32[0] ^= whitening[0]; + data32[1] ^= whitening[1]; + if (blockSize == 16) + { + data32[2] ^= whitening[0]; + data32[3] ^= whitening[1]; + } + + data32 += blockSize / sizeof(*data32); + } + + Memory::Erase (bufIV, sizeof (bufIV)); + } + + void EncryptionModeCBC::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + uint32 sectorIV[4]; + uint32 sectorWhitening[2]; + + while (sectorCount--) + { + if (IsOuterCBC (Ciphers)) + { + InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); + } + else + { + for (CipherList::const_iterator iCipherList = Ciphers.begin(); + iCipherList != Ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + CipherList cl; + cl.push_back (*iCipherList); + + InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); + } + } + + data += sectorSize; + sectorIndex++; + } + + Memory::Erase (sectorIV, sizeof (sectorIV)); + Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); + } + + void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const + { + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint64 iv64[4]; + uint32 *iv32 = (uint32 *) iv64; + + iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex); + iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex); + iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex); + if (blockSize == 16) + { + iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex); + } + + iv[0] = iv32[0]; + iv[1] = iv32[1]; + + if (blockSize == 8) + { + whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); + whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); + } + else + { + iv[2] = iv32[2]; + iv[3] = iv32[3]; + + whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); + whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); + } + } + + bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const + { + if (ciphers.size() < 2) + return false; + + size_t blockSize = ciphers.front()->GetBlockSize(); + + for (CipherList::const_iterator iCipherList = ciphers.begin(); + iCipherList != ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + if (c.GetBlockSize() != blockSize) + return false; + } + + return true; + } + + void EncryptionModeCBC::SetKey (const ConstBufferPtr &key) + { + if (key.Size() != GetKeySize ()) + throw ParameterIncorrect (SRC_POS); + + if (!KeySet) + IV.Allocate (GetKeySize ()); + + IV.CopyFrom (key); + KeySet = true; + } +} |