diff options
Diffstat (limited to 'src/Volume/EncryptionModeLRW.cpp')
-rw-r--r-- | src/Volume/EncryptionModeLRW.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/Volume/EncryptionModeLRW.cpp b/src/Volume/EncryptionModeLRW.cpp new file mode 100644 index 00000000..38731d5d --- /dev/null +++ b/src/Volume/EncryptionModeLRW.cpp @@ -0,0 +1,195 @@ +/* + 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 "EncryptionModeLRW.h" +#include "Common/GfMul.h" + +namespace TrueCrypt +{ + void EncryptionModeLRW::Decrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + DecryptBuffer (data, length, 1); + } + + void EncryptionModeLRW::DecryptBuffer (byte *data, uint64 length, uint64 blockIndex) const + { + size_t blockSize = Ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + byte i[8]; + *(uint64 *)i = Endian::Big (blockIndex); + + byte t[Cipher::MaxBlockSize]; + + for (unsigned int b = 0; b < length / blockSize; b++) + { + if (blockSize == 8) + { + Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor64 ((uint64 *)data, (uint64 *)t); + } + else + { + Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor128 ((uint64 *)data, (uint64 *)t); + } + + 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 (data); + } + + if (blockSize == 8) + Xor64 ((uint64 *)data, (uint64 *)t); + else + Xor128 ((uint64 *)data, (uint64 *)t); + + data += blockSize; + IncrementBlockIndex (i); + } + + Memory::Erase (t, sizeof (t)); + } + + void EncryptionModeLRW::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + DecryptBuffer (data, + sectorCount * sectorSize, + SectorToBlockIndex (sectorIndex)); + } + + void EncryptionModeLRW::Encrypt (byte *data, uint64 length) const + { + ValidateState (); + EncryptBuffer (data, length, 1); + } + + void EncryptionModeLRW::EncryptBuffer (byte *data, uint64 length, uint64 blockIndex) const + { + size_t blockSize = Ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + byte i[8]; + *(uint64 *)i = Endian::Big (blockIndex); + + byte t[Cipher::MaxBlockSize]; + + for (unsigned int b = 0; b < length / blockSize; b++) + { + if (blockSize == 8) + { + Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor64 ((uint64 *)data, (uint64 *)t); + } + else + { + Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor128 ((uint64 *)data, (uint64 *)t); + } + + 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 (data); + } + + if (blockSize == 8) + Xor64 ((uint64 *)data, (uint64 *)t); + else + Xor128 ((uint64 *)data, (uint64 *)t); + + data += blockSize; + IncrementBlockIndex (i); + } + + Memory::Erase (t, sizeof (t)); + } + + void EncryptionModeLRW::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + EncryptBuffer (data, + sectorCount * sectorSize, + SectorToBlockIndex (sectorIndex)); + } + + void EncryptionModeLRW::IncrementBlockIndex (byte *index) const + { + if (index[7] != 0xff) + index[7]++; + else + *(uint64 *)index = Endian::Big ( Endian::Big (*(uint64 *)index) + 1 ); + } + + uint64 EncryptionModeLRW::SectorToBlockIndex (uint64 sectorIndex) const + { + sectorIndex -= SectorOffset; + + switch (Ciphers.front()->GetBlockSize()) + { + case 8: + return (sectorIndex << 6) | 1; + + case 16: + return (sectorIndex << 5) | 1; + + default: + throw ParameterIncorrect (SRC_POS); + } + } + + void EncryptionModeLRW::SetKey (const ConstBufferPtr &key) + { + if (key.Size() != 16) + throw ParameterIncorrect (SRC_POS); + + if (!KeySet) + GfContext.Allocate (sizeof (GfCtx)); + + if (!Gf64TabInit ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) + throw bad_alloc(); + + if (!Gf128Tab64Init ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) + throw bad_alloc(); + + Key.CopyFrom (key); + KeySet = true; + } + + void EncryptionModeLRW::Xor64 (uint64 *a, const uint64 *b) const + { + *a ^= *b; + } + + void EncryptionModeLRW::Xor128 (uint64 *a, const uint64 *b) const + { + *a++ ^= *b++; + *a ^= *b; + } +} |