mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 19:08:26 -06:00
Add TrueCrypt 7.1a MacOSX/Linux specific source files.
This commit is contained in:
335
src/Volume/EncryptionModeCBC.cpp
Normal file
335
src/Volume/EncryptionModeCBC.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user