1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-12 03:18:26 -06:00

Add TrueCrypt 7.1a MacOSX/Linux specific source files.

This commit is contained in:
Mounir IDRASSI
2014-05-31 18:44:53 +02:00
parent 97011f179c
commit 7ffce028d0
203 changed files with 52120 additions and 0 deletions

314
src/Volume/Cipher.cpp Normal file
View File

@@ -0,0 +1,314 @@
/*
Copyright (c) 2008-2010 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/Platform.h"
#include "Cipher.h"
#include "Crypto/Aes.h"
#include "Crypto/Blowfish.h"
#include "Crypto/Des.h"
#include "Crypto/Cast.h"
#include "Crypto/Serpent.h"
#include "Crypto/Twofish.h"
#ifdef TC_AES_HW_CPU
# include "Crypto/Aes_hw_cpu.h"
#endif
namespace TrueCrypt
{
Cipher::Cipher () : Initialized (false)
{
}
Cipher::~Cipher ()
{
}
void Cipher::DecryptBlock (byte *data) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
Decrypt (data);
}
void Cipher::DecryptBlocks (byte *data, size_t blockCount) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
while (blockCount-- > 0)
{
Decrypt (data);
data += GetBlockSize();
}
}
void Cipher::EncryptBlock (byte *data) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
Encrypt (data);
}
void Cipher::EncryptBlocks (byte *data, size_t blockCount) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
while (blockCount-- > 0)
{
Encrypt (data);
data += GetBlockSize();
}
}
CipherList Cipher::GetAvailableCiphers ()
{
CipherList l;
l.push_back (shared_ptr <Cipher> (new CipherAES ()));
l.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
l.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
l.push_back (shared_ptr <Cipher> (new CipherBlowfish ()));
l.push_back (shared_ptr <Cipher> (new CipherCast5 ()));
l.push_back (shared_ptr <Cipher> (new CipherTripleDES ()));
return l;
}
void Cipher::SetKey (const ConstBufferPtr &key)
{
if (key.Size() != GetKeySize ())
throw ParameterIncorrect (SRC_POS);
if (!Initialized)
ScheduledKey.Allocate (GetScheduledKeySize ());
SetCipherKey (key);
Key.CopyFrom (key);
Initialized = true;
}
#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
#undef TC_EXCEPTION_NODECL
#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CipherException);
// AES
void CipherAES::Decrypt (byte *data) const
{
#ifdef TC_AES_HW_CPU
if (IsHwSupportAvailable())
aes_hw_cpu_decrypt (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx), data);
else
#endif
aes_decrypt (data, data, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx)));
}
void CipherAES::DecryptBlocks (byte *data, size_t blockCount) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
#ifdef TC_AES_HW_CPU
if ((blockCount & (32 - 1)) == 0
&& IsHwSupportAvailable())
{
while (blockCount > 0)
{
aes_hw_cpu_decrypt_32_blocks (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx), data);
data += 32 * GetBlockSize();
blockCount -= 32;
}
}
else
#endif
Cipher::DecryptBlocks (data, blockCount);
}
void CipherAES::Encrypt (byte *data) const
{
#ifdef TC_AES_HW_CPU
if (IsHwSupportAvailable())
aes_hw_cpu_encrypt (ScheduledKey.Ptr(), data);
else
#endif
aes_encrypt (data, data, (aes_encrypt_ctx *) ScheduledKey.Ptr());
}
void CipherAES::EncryptBlocks (byte *data, size_t blockCount) const
{
if (!Initialized)
throw NotInitialized (SRC_POS);
#ifdef TC_AES_HW_CPU
if ((blockCount & (32 - 1)) == 0
&& IsHwSupportAvailable())
{
while (blockCount > 0)
{
aes_hw_cpu_encrypt_32_blocks (ScheduledKey.Ptr(), data);
data += 32 * GetBlockSize();
blockCount -= 32;
}
}
else
#endif
Cipher::EncryptBlocks (data, blockCount);
}
size_t CipherAES::GetScheduledKeySize () const
{
return sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx);
}
bool CipherAES::IsHwSupportAvailable () const
{
#ifdef TC_AES_HW_CPU
static bool state = false;
static bool stateValid = false;
if (!stateValid)
{
state = is_aes_hw_cpu_supported() ? true : false;
stateValid = true;
}
return state && HwSupportEnabled;
#else
return false;
#endif
}
void CipherAES::SetCipherKey (const byte *key)
{
if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ScheduledKey.Ptr()) != EXIT_SUCCESS)
throw CipherInitError (SRC_POS);
if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS)
throw CipherInitError (SRC_POS);
}
// Blowfish
void CipherBlowfish::Decrypt (byte *data) const
{
BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 0);
}
void CipherBlowfish::Encrypt (byte *data) const
{
BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 1);
}
size_t CipherBlowfish::GetScheduledKeySize () const
{
return sizeof (BF_KEY);
}
void CipherBlowfish::SetCipherKey (const byte *key)
{
BlowfishSetKey ((BF_KEY *) ScheduledKey.Ptr(), static_cast<int> (GetKeySize ()), (unsigned char *) key);
}
// CAST5
void CipherCast5::Decrypt (byte *data) const
{
Cast5Decrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr());
}
void CipherCast5::Encrypt (byte *data) const
{
Cast5Encrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr());
}
size_t CipherCast5::GetScheduledKeySize () const
{
return sizeof (CAST_KEY);
}
void CipherCast5::SetCipherKey (const byte *key)
{
Cast5SetKey ((CAST_KEY *) ScheduledKey.Ptr(), static_cast<int> (GetKeySize ()), (unsigned char *) key);
}
// Serpent
void CipherSerpent::Decrypt (byte *data) const
{
serpent_decrypt (data, data, ScheduledKey);
}
void CipherSerpent::Encrypt (byte *data) const
{
serpent_encrypt (data, data, ScheduledKey);
}
size_t CipherSerpent::GetScheduledKeySize () const
{
return 140*4;
}
void CipherSerpent::SetCipherKey (const byte *key)
{
serpent_set_key (key, static_cast<int> (GetKeySize ()), ScheduledKey);
}
// Triple-DES
void CipherTripleDES::Decrypt (byte *data) const
{
TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 0);
}
void CipherTripleDES::Encrypt (byte *data) const
{
TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 1);
}
size_t CipherTripleDES::GetScheduledKeySize () const
{
return sizeof (TDES_KEY);
}
void CipherTripleDES::SetCipherKey (const byte *key)
{
TripleDesSetKey (key, GetKeySize(), (TDES_KEY *) ScheduledKey.Ptr());
}
// Twofish
void CipherTwofish::Decrypt (byte *data) const
{
twofish_decrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data);
}
void CipherTwofish::Encrypt (byte *data) const
{
twofish_encrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data);
}
size_t CipherTwofish::GetScheduledKeySize () const
{
return TWOFISH_KS;
}
void CipherTwofish::SetCipherKey (const byte *key)
{
twofish_set_key ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *) key, static_cast<int> (GetKeySize ()) * 8);
}
bool Cipher::HwSupportEnabled = true;
}

129
src/Volume/Cipher.h Normal file
View File

@@ -0,0 +1,129 @@
/*
Copyright (c) 2008-2010 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.
*/
#ifndef TC_HEADER_Encryption_Ciphers
#define TC_HEADER_Encryption_Ciphers
#include "Platform/Platform.h"
namespace TrueCrypt
{
class Cipher;
typedef vector < shared_ptr <Cipher> > CipherList;
class Cipher
{
public:
virtual ~Cipher ();
virtual void DecryptBlock (byte *data) const;
virtual void DecryptBlocks (byte *data, size_t blockCount) const;
static void EnableHwSupport (bool enable) { HwSupportEnabled = enable; }
virtual void EncryptBlock (byte *data) const;
virtual void EncryptBlocks (byte *data, size_t blockCount) const;
static CipherList GetAvailableCiphers ();
virtual size_t GetBlockSize () const = 0;
virtual const SecureBuffer &GetKey () const { return Key; }
virtual size_t GetKeySize () const = 0;
virtual wstring GetName () const = 0;
virtual shared_ptr <Cipher> GetNew () const = 0;
virtual bool IsHwSupportAvailable () const { return false; }
static bool IsHwSupportEnabled () { return HwSupportEnabled; }
virtual void SetKey (const ConstBufferPtr &key);
static const int MaxBlockSize = 16;
protected:
Cipher ();
virtual void Decrypt (byte *data) const = 0;
virtual void Encrypt (byte *data) const = 0;
virtual size_t GetScheduledKeySize () const = 0;
virtual void SetCipherKey (const byte *key) = 0;
static bool HwSupportEnabled;
bool Initialized;
SecureBuffer Key;
SecureBuffer ScheduledKey;
private:
Cipher (const Cipher &);
Cipher &operator= (const Cipher &);
};
struct CipherException : public Exception
{
protected:
CipherException () { }
CipherException (const string &message) : Exception (message) { }
CipherException (const string &message, const wstring &subject) : Exception (message, subject) { }
};
#define TC_CIPHER(NAME, BLOCK_SIZE, KEY_SIZE) \
class TC_JOIN (Cipher,NAME) : public Cipher \
{ \
public: \
TC_JOIN (Cipher,NAME) () { } \
virtual ~TC_JOIN (Cipher,NAME) () { } \
\
virtual size_t GetBlockSize () const { return BLOCK_SIZE; }; \
virtual size_t GetKeySize () const { return KEY_SIZE; }; \
virtual wstring GetName () const { return L###NAME; }; \
virtual shared_ptr <Cipher> GetNew () const { return shared_ptr <Cipher> (new TC_JOIN (Cipher,NAME)()); } \
TC_CIPHER_ADD_METHODS \
\
protected: \
virtual void Decrypt (byte *data) const; \
virtual void Encrypt (byte *data) const; \
virtual size_t GetScheduledKeySize () const; \
virtual void SetCipherKey (const byte *key); \
\
private: \
TC_JOIN (Cipher,NAME) (const TC_JOIN (Cipher,NAME) &); \
TC_JOIN (Cipher,NAME) &operator= (const TC_JOIN (Cipher,NAME) &); \
}
#define TC_CIPHER_ADD_METHODS \
virtual void DecryptBlocks (byte *data, size_t blockCount) const; \
virtual void EncryptBlocks (byte *data, size_t blockCount) const; \
virtual bool IsHwSupportAvailable () const;
TC_CIPHER (AES, 16, 32);
#undef TC_CIPHER_ADD_METHODS
#define TC_CIPHER_ADD_METHODS
TC_CIPHER (Blowfish, 8, 56);
TC_CIPHER (Cast5, 8, 16);
TC_CIPHER (Serpent, 16, 32);
TC_CIPHER (TripleDES, 8, 24);
TC_CIPHER (Twofish, 16, 32);
#undef TC_CIPHER
#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,CipherException)
#undef TC_EXCEPTION_SET
#define TC_EXCEPTION_SET \
TC_EXCEPTION (CipherInitError); \
TC_EXCEPTION (WeakKeyDetected);
TC_EXCEPTION_SET;
#undef TC_EXCEPTION
#if (defined (TC_ARCH_X86) || defined (TC_ARCH_X64)) && !defined (__ppc__)
# define TC_AES_HW_CPU
#endif
}
#endif // TC_HEADER_Encryption_Ciphers

44
src/Volume/Crc32.h Normal file
View File

@@ -0,0 +1,44 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_Crc32
#define TC_HEADER_Encryption_Crc32
#include "Platform/Platform.h"
#include "Common/Crc.h"
namespace TrueCrypt
{
class Crc32
{
public:
Crc32 () : CrcValue (0xffffFFFF) { };
virtual ~Crc32 () { };
uint32 Get () const { return CrcValue ^ 0xffffFFFF; }
uint32 Process (byte data)
{
return CrcValue = crc_32_tab[(byte) (CrcValue ^ data)] ^ (CrcValue >> 8);
}
static uint32 ProcessBuffer (const ConstBufferPtr &buffer)
{
return ::GetCrc32 (const_cast<byte *> (buffer.Get()), static_cast<int> (buffer.Size()));
}
protected:
uint32 CrcValue;
private:
Crc32 (const Crc32 &);
Crc32 &operator= (const Crc32 &);
};
}
#endif // TC_HEADER_Encryption_Crc32

View File

@@ -0,0 +1,345 @@
/*
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 "EncryptionAlgorithm.h"
#include "EncryptionModeCBC.h"
#include "EncryptionModeLRW.h"
#include "EncryptionModeXTS.h"
namespace TrueCrypt
{
EncryptionAlgorithm::EncryptionAlgorithm () : Deprecated (false)
{
}
EncryptionAlgorithm::~EncryptionAlgorithm ()
{
}
void EncryptionAlgorithm::Decrypt (byte *data, uint64 length) const
{
if_debug (ValidateState ());
Mode->Decrypt (data, length);
}
void EncryptionAlgorithm::Decrypt (const BufferPtr &data) const
{
Decrypt (data, data.Size());
}
void EncryptionAlgorithm::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
if_debug (ValidateState());
Mode->DecryptSectors (data, sectorIndex, sectorCount, sectorSize);
}
void EncryptionAlgorithm::Encrypt (byte *data, uint64 length) const
{
if_debug (ValidateState());
Mode->Encrypt (data, length);
}
void EncryptionAlgorithm::Encrypt (const BufferPtr &data) const
{
Encrypt (data, data.Size());
}
void EncryptionAlgorithm::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
if_debug (ValidateState ());
Mode->EncryptSectors (data, sectorIndex, sectorCount, sectorSize);
}
EncryptionAlgorithmList EncryptionAlgorithm::GetAvailableAlgorithms ()
{
EncryptionAlgorithmList l;
l.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfishSerpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Blowfish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Cast5 ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new TripleDES ()));
return l;
}
size_t EncryptionAlgorithm::GetLargestKeySize (const EncryptionAlgorithmList &algorithms)
{
size_t largestKeySize = 0;
foreach_ref (const EncryptionAlgorithm &ea, algorithms)
{
if (ea.GetKeySize() > largestKeySize)
largestKeySize = ea.GetKeySize();
}
return largestKeySize;
}
size_t EncryptionAlgorithm::GetKeySize () const
{
if (Ciphers.size() < 1)
throw NotInitialized (SRC_POS);
size_t keySize = 0;
foreach_ref (const Cipher &c, Ciphers)
keySize += c.GetKeySize();
return keySize;
}
size_t EncryptionAlgorithm::GetMaxBlockSize () const
{
size_t blockSize = 0;
foreach_ref (const Cipher &c, Ciphers)
if (c.GetBlockSize() > blockSize)
blockSize = c.GetBlockSize();
return blockSize;
}
size_t EncryptionAlgorithm::GetMinBlockSize () const
{
size_t blockSize = 0;
foreach_ref (const Cipher &c, Ciphers)
if (blockSize == 0 || c.GetBlockSize() < blockSize)
blockSize = c.GetBlockSize();
return blockSize;
}
shared_ptr <EncryptionMode> EncryptionAlgorithm::GetMode () const
{
if (Mode.get() == nullptr)
throw NotInitialized (SRC_POS);
return Mode;
}
wstring EncryptionAlgorithm::GetName () const
{
if (Ciphers.size() < 1)
throw NotInitialized (SRC_POS);
wstring name;
foreach_reverse_ref (const Cipher &c, Ciphers)
{
if (name.empty())
name = c.GetName();
else
name += wstring (L"-") + c.GetName();
}
return name;
}
bool EncryptionAlgorithm::IsModeSupported (const EncryptionMode &mode) const
{
bool supported = false;
foreach_ref (const EncryptionMode &em, SupportedModes)
{
if (typeid (mode) == typeid (em))
{
supported = true;
break;
}
}
return supported;
}
bool EncryptionAlgorithm::IsModeSupported (const shared_ptr <EncryptionMode> mode) const
{
return IsModeSupported (*mode);
}
void EncryptionAlgorithm::SetMode (shared_ptr <EncryptionMode> mode)
{
if (!IsModeSupported (*mode))
throw ParameterIncorrect (SRC_POS);
mode->SetCiphers (Ciphers);
Mode = mode;
}
void EncryptionAlgorithm::SetKey (const ConstBufferPtr &key)
{
if (Ciphers.size() < 1)
throw NotInitialized (SRC_POS);
if (GetKeySize() != key.Size())
throw ParameterIncorrect (SRC_POS);
size_t keyOffset = 0;
foreach_ref (Cipher &c, Ciphers)
{
c.SetKey (key.GetRange (keyOffset, c.GetKeySize()));
keyOffset += c.GetKeySize();
}
}
void EncryptionAlgorithm::ValidateState () const
{
if (Ciphers.size() < 1 || Mode.get() == nullptr)
throw NotInitialized (SRC_POS);
}
// AES
AES::AES ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// AES-Blowfish
AESBlowfish::AESBlowfish ()
{
Deprecated = true;
Ciphers.push_back (shared_ptr <Cipher> (new CipherBlowfish ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// AES-Blowfish-Serpent
AESBlowfishSerpent::AESBlowfishSerpent ()
{
Deprecated = true;
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherBlowfish ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// AES-Twofish
AESTwofish::AESTwofish ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// AES-Twofish-Serpent
AESTwofishSerpent::AESTwofishSerpent ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Blowfish
Blowfish::Blowfish ()
{
Deprecated = true;
Ciphers.push_back (shared_ptr <Cipher> (new CipherBlowfish()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// CAST5
Cast5::Cast5 ()
{
Deprecated = true;
Ciphers.push_back (shared_ptr <Cipher> (new CipherCast5()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Serpent
Serpent::Serpent ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Serpent-AES
SerpentAES::SerpentAES ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Triple-DES
TripleDES::TripleDES ()
{
Deprecated = true;
Ciphers.push_back (shared_ptr <Cipher> (new CipherTripleDES()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Twofish
Twofish::Twofish ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherTwofish()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Twofish-Serpent
TwofishSerpent::TwofishSerpent ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
// Serpent-Twofish-AES
SerpentTwofishAES::SerpentTwofishAES ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherAES ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
Ciphers.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
}

View File

@@ -0,0 +1,93 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_EncryptionAlgorithm
#define TC_HEADER_Encryption_EncryptionAlgorithm
#include "Platform/Platform.h"
#include "Cipher.h"
#include "EncryptionMode.h"
namespace TrueCrypt
{
class EncryptionAlgorithm;
typedef list < shared_ptr <EncryptionAlgorithm> > EncryptionAlgorithmList;
class EncryptionAlgorithm
{
public:
virtual ~EncryptionAlgorithm ();
virtual void Decrypt (byte *data, uint64 length) const;
virtual void Decrypt (const BufferPtr &data) const;
virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void Encrypt (byte *data, uint64 length) const;
virtual void Encrypt (const BufferPtr &data) const;
virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
static EncryptionAlgorithmList GetAvailableAlgorithms ();
virtual const CipherList &GetCiphers () const { return Ciphers; }
virtual shared_ptr <EncryptionAlgorithm> GetNew () const = 0;
virtual size_t GetMaxBlockSize () const;
virtual size_t GetMinBlockSize () const;
static size_t GetLargestKeySize (const EncryptionAlgorithmList &algorithms);
virtual size_t GetKeySize () const;
virtual shared_ptr <EncryptionMode> GetMode () const;
virtual wstring GetName () const;
bool IsDeprecated () const { return Deprecated; }
virtual bool IsModeSupported (const EncryptionMode &mode) const;
virtual bool IsModeSupported (const shared_ptr <EncryptionMode> mode) const;
virtual void SetKey (const ConstBufferPtr &key);
virtual void SetMode (shared_ptr <EncryptionMode> mode);
protected:
EncryptionAlgorithm ();
void ValidateState () const;
CipherList Ciphers;
bool Deprecated;
shared_ptr <EncryptionMode> Mode;
EncryptionModeList SupportedModes;
private:
EncryptionAlgorithm (const EncryptionAlgorithm &);
EncryptionAlgorithm &operator= (const EncryptionAlgorithm &);
};
#define TC_ENCRYPTION_ALGORITHM(NAME) \
class NAME : public EncryptionAlgorithm \
{ \
public: \
NAME (); \
virtual ~NAME () { } \
\
virtual shared_ptr <EncryptionAlgorithm> GetNew () const { return shared_ptr <EncryptionAlgorithm> (new NAME()); } \
\
private: \
NAME (const NAME &); \
NAME &operator= (const NAME &); \
}
TC_ENCRYPTION_ALGORITHM (AES);
TC_ENCRYPTION_ALGORITHM (AESBlowfish);
TC_ENCRYPTION_ALGORITHM (AESBlowfishSerpent);
TC_ENCRYPTION_ALGORITHM (AESTwofish);
TC_ENCRYPTION_ALGORITHM (AESTwofishSerpent);
TC_ENCRYPTION_ALGORITHM (Blowfish);
TC_ENCRYPTION_ALGORITHM (Cast5);
TC_ENCRYPTION_ALGORITHM (Serpent);
TC_ENCRYPTION_ALGORITHM (SerpentAES);
TC_ENCRYPTION_ALGORITHM (TripleDES);
TC_ENCRYPTION_ALGORITHM (Twofish);
TC_ENCRYPTION_ALGORITHM (TwofishSerpent);
TC_ENCRYPTION_ALGORITHM (SerpentTwofishAES);
#undef TC_ENCRYPTION_ALGORITHM
}
#endif // TC_HEADER_Encryption_EncryptionAlgorithm

View File

@@ -0,0 +1,63 @@
/*
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 "EncryptionMode.h"
#include "EncryptionModeCBC.h"
#include "EncryptionModeLRW.h"
#include "EncryptionModeXTS.h"
#include "EncryptionThreadPool.h"
namespace TrueCrypt
{
EncryptionMode::EncryptionMode () : KeySet (false), SectorOffset (0)
{
}
EncryptionMode::~EncryptionMode ()
{
}
void EncryptionMode::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::DecryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize);
}
void EncryptionMode::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::EncryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize);
}
EncryptionModeList EncryptionMode::GetAvailableModes ()
{
EncryptionModeList l;
l.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
l.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
l.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
return l;
}
void EncryptionMode::ValidateState () const
{
if (!KeySet || Ciphers.size() < 1)
throw NotInitialized (SRC_POS);
}
void EncryptionMode::ValidateParameters (byte *data, uint64 length) const
{
if ((Ciphers.size() > 0 && (length % Ciphers.front()->GetBlockSize()) != 0))
throw ParameterIncorrect (SRC_POS);
}
void EncryptionMode::ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const
{
if (sectorCount == 0 || sectorSize == 0 || (sectorSize % EncryptionDataUnitSize) != 0)
throw ParameterIncorrect (SRC_POS);
}
}

View File

@@ -0,0 +1,62 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_EncryptionMode
#define TC_HEADER_Encryption_EncryptionMode
#include "Platform/Platform.h"
#include "Common/Crypto.h"
#include "Cipher.h"
namespace TrueCrypt
{
class EncryptionMode;
typedef list < shared_ptr <EncryptionMode> > EncryptionModeList;
class EncryptionMode
{
public:
virtual ~EncryptionMode ();
virtual void Decrypt (byte *data, uint64 length) const = 0;
virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0;
virtual void Encrypt (byte *data, uint64 length) const = 0;
virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0;
static EncryptionModeList GetAvailableModes ();
virtual const SecureBuffer &GetKey () const { throw NotApplicable (SRC_POS); }
virtual size_t GetKeySize () const = 0;
virtual wstring GetName () const = 0;
virtual shared_ptr <EncryptionMode> GetNew () const = 0;
virtual uint64 GetSectorOffset () const { return SectorOffset; }
virtual bool IsKeySet () const { return KeySet; }
virtual void SetKey (const ConstBufferPtr &key) = 0;
virtual void SetCiphers (const CipherList &ciphers) { Ciphers = ciphers; }
virtual void SetSectorOffset (int64 offset) { SectorOffset = offset; }
protected:
EncryptionMode ();
virtual void ValidateState () const;
void ValidateParameters (byte *data, uint64 length) const;
virtual void ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const;
static const size_t EncryptionDataUnitSize = ENCRYPTION_DATA_UNIT_SIZE;
CipherList Ciphers;
bool KeySet;
uint64 SectorOffset;
private:
EncryptionMode (const EncryptionMode &);
EncryptionMode &operator= (const EncryptionMode &);
};
}
#endif // TC_HEADER_Encryption_EncryptionMode

View 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;
}
}

View File

@@ -0,0 +1,47 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_EncryptionModeCBC
#define TC_HEADER_Encryption_EncryptionModeCBC
#include "Platform/Platform.h"
#include "EncryptionMode.h"
namespace TrueCrypt
{
class EncryptionModeCBC : public EncryptionMode
{
public:
EncryptionModeCBC () { }
virtual ~EncryptionModeCBC () { }
virtual void Decrypt (byte *data, uint64 length) const;
virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void Encrypt (byte *data, uint64 length) const;
virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual size_t GetKeySize () const { return 32; };
virtual wstring GetName () const { return L"CBC"; };
virtual shared_ptr <EncryptionMode> GetNew () const { return shared_ptr <EncryptionMode> (new EncryptionModeCBC); }
virtual void SetKey (const ConstBufferPtr &key);
protected:
void DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const;
void EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const;
void InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const;
bool IsOuterCBC (const CipherList &ciphers) const;
SecureBuffer IV;
static const int WhiteningIVOffset = 8;
private:
EncryptionModeCBC (const EncryptionModeCBC &);
EncryptionModeCBC &operator= (const EncryptionModeCBC &);
};
}
#endif // TC_HEADER_Encryption_EncryptionModeCBC

View File

@@ -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;
}
}

View File

@@ -0,0 +1,50 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_EncryptionModeLRW
#define TC_HEADER_Encryption_EncryptionModeLRW
#include "Platform/Platform.h"
#include "EncryptionMode.h"
namespace TrueCrypt
{
class EncryptionModeLRW : public EncryptionMode
{
public:
EncryptionModeLRW () { }
virtual ~EncryptionModeLRW () { }
virtual void Decrypt (byte *data, uint64 length) const;
virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void Encrypt (byte *data, uint64 length) const;
virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual const SecureBuffer &GetKey () const { return Key; }
virtual size_t GetKeySize () const { return 16; };
virtual wstring GetName () const { return L"LRW"; };
virtual shared_ptr <EncryptionMode> GetNew () const { return shared_ptr <EncryptionMode> (new EncryptionModeLRW); }
virtual void SetKey (const ConstBufferPtr &key);
protected:
void DecryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const;
void EncryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const;
void IncrementBlockIndex (byte *index) const;
uint64 SectorToBlockIndex (uint64 sectorIndex) const;
void Xor64 (uint64 *a, const uint64 *b) const;
void Xor128 (uint64 *a, const uint64 *b) const;
SecureBuffer GfContext;
SecureBuffer Key;
private:
EncryptionModeLRW (const EncryptionModeLRW &);
EncryptionModeLRW &operator= (const EncryptionModeLRW &);
};
}
#endif // TC_HEADER_Encryption_EncryptionModeLRW

View File

@@ -0,0 +1,374 @@
/*
Copyright (c) 2008-2010 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 "EncryptionModeXTS.h"
#include "Common/Crypto.h"
namespace TrueCrypt
{
void EncryptionModeXTS::Encrypt (byte *data, uint64 length) const
{
EncryptBuffer (data, length, 0);
}
void EncryptionModeXTS::EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const
{
if_debug (ValidateState());
CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.begin();
for (CipherList::const_iterator iCipher = Ciphers.begin(); iCipher != Ciphers.end(); ++iCipher)
{
EncryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0);
++iSecondaryCipher;
}
assert (iSecondaryCipher == SecondaryCiphers.end());
}
void EncryptionModeXTS::EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const
{
byte finalCarry;
byte whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
byte whiteningValue [BYTES_PER_XTS_BLOCK];
byte byteBufUnitNo [BYTES_PER_XTS_BLOCK];
uint64 *whiteningValuesPtr64 = (uint64 *) whiteningValues;
uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue;
uint64 *bufPtr = (uint64 *) buffer;
uint64 *dataUnitBufPtr;
unsigned int startBlock = startCipherBlockNo, endBlock, block;
uint64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
uint64 blockCount, dataUnitNo;
startDataUnitNo += SectorOffset;
/* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */
// Convert the 64-bit data unit number into a little-endian 16-byte array.
// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
dataUnitNo = startDataUnitNo;
*((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
*((uint64 *) byteBufUnitNo + 1) = 0;
if (length % BYTES_PER_XTS_BLOCK)
TC_THROW_FATAL_EXCEPTION;
blockCount = length / BYTES_PER_XTS_BLOCK;
// Process all blocks in the buffer
while (blockCount > 0)
{
if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
endBlock = startBlock + (unsigned int) blockCount;
else
endBlock = BLOCKS_PER_XTS_DATA_UNIT;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
whiteningValuePtr64 = (uint64 *) whiteningValue;
// Encrypt the data unit number using the secondary key (in order to generate the first
// whitening value for this data unit)
*whiteningValuePtr64 = *((uint64 *) byteBufUnitNo);
*(whiteningValuePtr64 + 1) = 0;
secondaryCipher.EncryptBlock (whiteningValue);
// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
for (block = 0; block < endBlock; block++)
{
if (block >= startBlock)
{
*whiteningValuesPtr64-- = *whiteningValuePtr64++;
*whiteningValuesPtr64-- = *whiteningValuePtr64;
}
else
whiteningValuePtr64++;
// Derive the next whitening value
#if BYTE_ORDER == LITTLE_ENDIAN
// Little-endian platforms
finalCarry =
(*whiteningValuePtr64 & 0x8000000000000000ULL) ?
135 : 0;
*whiteningValuePtr64-- <<= 1;
if (*whiteningValuePtr64 & 0x8000000000000000ULL)
*(whiteningValuePtr64 + 1) |= 1;
*whiteningValuePtr64 <<= 1;
#else
// Big-endian platforms
finalCarry =
(*whiteningValuePtr64 & 0x80) ?
135 : 0;
*whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
whiteningValuePtr64--;
if (*whiteningValuePtr64 & 0x80)
*(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL;
*whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
#endif
whiteningValue[0] ^= finalCarry;
}
dataUnitBufPtr = bufPtr;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
// Encrypt all blocks in this data unit
for (block = startBlock; block < endBlock; block++)
{
// Pre-whitening
*bufPtr++ ^= *whiteningValuesPtr64--;
*bufPtr++ ^= *whiteningValuesPtr64--;
}
// Actual encryption
cipher.EncryptBlocks ((byte *) dataUnitBufPtr, endBlock - startBlock);
bufPtr = dataUnitBufPtr;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
for (block = startBlock; block < endBlock; block++)
{
// Post-whitening
*bufPtr++ ^= *whiteningValuesPtr64--;
*bufPtr++ ^= *whiteningValuesPtr64--;
}
blockCount -= endBlock - startBlock;
startBlock = 0;
dataUnitNo++;
*((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
}
FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}
void EncryptionModeXTS::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
EncryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE);
}
size_t EncryptionModeXTS::GetKeySize () const
{
if (Ciphers.empty())
throw NotInitialized (SRC_POS);
size_t keySize = 0;
foreach_ref (const Cipher &cipher, SecondaryCiphers)
{
keySize += cipher.GetKeySize();
}
return keySize;
}
void EncryptionModeXTS::Decrypt (byte *data, uint64 length) const
{
DecryptBuffer (data, length, 0);
}
void EncryptionModeXTS::DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const
{
if_debug (ValidateState());
CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.end();
for (CipherList::const_reverse_iterator iCipher = Ciphers.rbegin(); iCipher != Ciphers.rend(); ++iCipher)
{
--iSecondaryCipher;
DecryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0);
}
assert (iSecondaryCipher == SecondaryCiphers.begin());
}
void EncryptionModeXTS::DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const
{
byte finalCarry;
byte whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
byte whiteningValue [BYTES_PER_XTS_BLOCK];
byte byteBufUnitNo [BYTES_PER_XTS_BLOCK];
uint64 *whiteningValuesPtr64 = (uint64 *) whiteningValues;
uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue;
uint64 *bufPtr = (uint64 *) buffer;
uint64 *dataUnitBufPtr;
unsigned int startBlock = startCipherBlockNo, endBlock, block;
uint64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
uint64 blockCount, dataUnitNo;
startDataUnitNo += SectorOffset;
// Convert the 64-bit data unit number into a little-endian 16-byte array.
// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
dataUnitNo = startDataUnitNo;
*((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
*((uint64 *) byteBufUnitNo + 1) = 0;
if (length % BYTES_PER_XTS_BLOCK)
TC_THROW_FATAL_EXCEPTION;
blockCount = length / BYTES_PER_XTS_BLOCK;
// Process all blocks in the buffer
while (blockCount > 0)
{
if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
endBlock = startBlock + (unsigned int) blockCount;
else
endBlock = BLOCKS_PER_XTS_DATA_UNIT;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
whiteningValuePtr64 = (uint64 *) whiteningValue;
// Encrypt the data unit number using the secondary key (in order to generate the first
// whitening value for this data unit)
*whiteningValuePtr64 = *((uint64 *) byteBufUnitNo);
*(whiteningValuePtr64 + 1) = 0;
secondaryCipher.EncryptBlock (whiteningValue);
// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
for (block = 0; block < endBlock; block++)
{
if (block >= startBlock)
{
*whiteningValuesPtr64-- = *whiteningValuePtr64++;
*whiteningValuesPtr64-- = *whiteningValuePtr64;
}
else
whiteningValuePtr64++;
// Derive the next whitening value
#if BYTE_ORDER == LITTLE_ENDIAN
// Little-endian platforms
finalCarry =
(*whiteningValuePtr64 & 0x8000000000000000ULL) ?
135 : 0;
*whiteningValuePtr64-- <<= 1;
if (*whiteningValuePtr64 & 0x8000000000000000ULL)
*(whiteningValuePtr64 + 1) |= 1;
*whiteningValuePtr64 <<= 1;
#else
// Big-endian platforms
finalCarry =
(*whiteningValuePtr64 & 0x80) ?
135 : 0;
*whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
whiteningValuePtr64--;
if (*whiteningValuePtr64 & 0x80)
*(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL;
*whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1);
#endif
whiteningValue[0] ^= finalCarry;
}
dataUnitBufPtr = bufPtr;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
// Decrypt blocks in this data unit
for (block = startBlock; block < endBlock; block++)
{
*bufPtr++ ^= *whiteningValuesPtr64--;
*bufPtr++ ^= *whiteningValuesPtr64--;
}
cipher.DecryptBlocks ((byte *) dataUnitBufPtr, endBlock - startBlock);
bufPtr = dataUnitBufPtr;
whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
for (block = startBlock; block < endBlock; block++)
{
*bufPtr++ ^= *whiteningValuesPtr64--;
*bufPtr++ ^= *whiteningValuesPtr64--;
}
blockCount -= endBlock - startBlock;
startBlock = 0;
dataUnitNo++;
*((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo);
}
FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}
void EncryptionModeXTS::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
{
DecryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE);
}
void EncryptionModeXTS::SetCiphers (const CipherList &ciphers)
{
EncryptionMode::SetCiphers (ciphers);
SecondaryCiphers.clear();
foreach_ref (const Cipher &cipher, ciphers)
{
SecondaryCiphers.push_back (cipher.GetNew());
}
if (SecondaryKey.Size() > 0)
SetSecondaryCipherKeys();
}
void EncryptionModeXTS::SetKey (const ConstBufferPtr &key)
{
SecondaryKey.Allocate (key.Size());
SecondaryKey.CopyFrom (key);
if (!SecondaryCiphers.empty())
SetSecondaryCipherKeys();
}
void EncryptionModeXTS::SetSecondaryCipherKeys ()
{
size_t keyOffset = 0;
foreach_ref (Cipher &cipher, SecondaryCiphers)
{
cipher.SetKey (SecondaryKey.GetRange (keyOffset, cipher.GetKeySize()));
keyOffset += cipher.GetKeySize();
}
KeySet = true;
}
}

View File

@@ -0,0 +1,50 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_EncryptionModeXTS
#define TC_HEADER_Volume_EncryptionModeXTS
#include "Platform/Platform.h"
#include "EncryptionMode.h"
namespace TrueCrypt
{
class EncryptionModeXTS : public EncryptionMode
{
public:
EncryptionModeXTS () { }
virtual ~EncryptionModeXTS () { }
virtual void Decrypt (byte *data, uint64 length) const;
virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual void Encrypt (byte *data, uint64 length) const;
virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const;
virtual const SecureBuffer &GetKey () const { return SecondaryKey; }
virtual size_t GetKeySize () const;
virtual wstring GetName () const { return L"XTS"; };
virtual shared_ptr <EncryptionMode> GetNew () const { return shared_ptr <EncryptionMode> (new EncryptionModeXTS); }
virtual void SetCiphers (const CipherList &ciphers);
virtual void SetKey (const ConstBufferPtr &key);
protected:
void DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const;
void DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const;
void EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const;
void EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const;
void SetSecondaryCipherKeys ();
SecureBuffer SecondaryKey;
CipherList SecondaryCiphers;
private:
EncryptionModeXTS (const EncryptionModeXTS &);
EncryptionModeXTS &operator= (const EncryptionModeXTS &);
};
}
#endif // TC_HEADER_Volume_EncryptionModeXTS

View File

@@ -0,0 +1,890 @@
/*
Copyright (c) 2008-2010 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 "Cipher.h"
#include "Common/Crc.h"
#include "Crc32.h"
#include "EncryptionAlgorithm.h"
#include "EncryptionMode.h"
#include "EncryptionModeCBC.h"
#include "EncryptionModeLRW.h"
#include "EncryptionModeXTS.h"
#include "EncryptionTest.h"
#include "Pkcs5Kdf.h"
namespace TrueCrypt
{
void EncryptionTest::TestAll ()
{
TestAll (false);
TestAll (true);
}
void EncryptionTest::TestAll (bool enableCpuEncryptionSupport)
{
bool hwSupportEnabled = Cipher::IsHwSupportEnabled();
finally_do_arg (bool, hwSupportEnabled, { Cipher::EnableHwSupport (finally_arg); });
Cipher::EnableHwSupport (enableCpuEncryptionSupport);
TestCiphers();
TestXtsAES();
TestXts();
TestLegacyModes();
TestPkcs5();
}
void EncryptionTest::TestLegacyModes ()
{
byte buf[ENCRYPTION_DATA_UNIT_SIZE * 2];
byte iv[32];
unsigned int i;
uint32 crc;
uint64 secNo = 0x0234567890ABCDEFull;
for (i = 0; i < sizeof (buf); i++)
buf[i] = (byte) i;
for (i = 0; i < sizeof (iv); i++)
iv[i] = (byte) i;
EncryptionModeList encModes = EncryptionMode::GetAvailableModes ();
foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms())
{
foreach (shared_ptr <EncryptionMode> mode, encModes)
{
if (typeid (*mode) == typeid (EncryptionModeXTS))
continue;
if (!mode->IsKeySet())
{
mode->SetKey (ConstBufferPtr (iv, mode->GetKeySize()));
mode->SetSectorOffset (1);
}
if (ea.IsModeSupported (mode))
{
ea.SetMode (mode);
ea.SetKey (ConstBufferPtr (buf, ea.GetKeySize()));
ea.EncryptSectors (buf, secNo, sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
ea.DecryptSectors (buf, secNo, sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
ea.EncryptSectors (buf, secNo, sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
crc = ::GetCrc32 (buf, sizeof (buf));
if (typeid (*mode) == typeid (EncryptionModeLRW))
{
if (typeid (ea) == typeid (AES) && crc != 0x5237acf9) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESTwofish) && crc != 0x4ed0fd80) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0xea04b3cf) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Blowfish) && crc != 0xf94d5300) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Cast5) && crc != 0x33971e82) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Serpent) && crc != 0x7fb86805) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (TripleDES) && crc != 0x2b20bb84) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Twofish) && crc != 0xa9de0f0b) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xca65c5cd) throw TestFailed (SRC_POS);
}
if (typeid (*mode) == typeid (EncryptionModeCBC))
{
if (typeid (ea) == typeid (AES) && crc != 0x2274f53d) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESBlowfish) && crc != 0xa7a80c84) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESBlowfishSerpent) && crc != 0xa0584562) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESTwofish) && crc != 0x3c226444) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0x5e5e77fd) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Blowfish) && crc != 0x033899a1) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Cast5) && crc != 0x331cecc7) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (Serpent) && crc != 0x42dff3d4) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (TripleDES) && crc != 0xfe497d0c) throw TestFailed (SRC_POS);
if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xa7b659f3) throw TestFailed (SRC_POS);
}
ea.DecryptSectors (buf, secNo, sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
}
}
}
}
struct CipherTestVector
{
byte Key[32];
byte Plaintext[16];
byte Ciphertext[16];
};
static const CipherTestVector AESTestVectors[] =
{
{
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
},
{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
},
{
0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89
}
}
};
static const CipherTestVector SerpentTestVectors[] =
{
{
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
},
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
},
{
0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c
}
}
};
static const CipherTestVector TwofishTestVectors[] =
{
{
{
0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F
},
{
0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6
},
{
0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA
}
}
};
static void TestCipher (Cipher &cipher, const CipherTestVector *testVector, size_t testVectorCount)
{
Buffer buffer (cipher.GetBlockSize());
for (size_t i = 0; i < testVectorCount; ++i)
{
cipher.SetKey (ConstBufferPtr (testVector[i].Key, sizeof (testVector[i].Key)));
buffer.CopyFrom (ConstBufferPtr (testVector[i].Plaintext, sizeof (testVector[i].Plaintext)));
cipher.EncryptBlock (buffer);
if (memcmp (buffer, testVector[i].Ciphertext, buffer.Size()) != 0)
throw TestFailed (SRC_POS);
}
}
void EncryptionTest::TestCiphers ()
{
CipherAES aes;
TestCipher (aes, AESTestVectors, array_capacity (AESTestVectors));
Buffer testData (1024);
for (size_t i = 0; i < testData.Size(); ++i)
{
testData[i] = (byte) i;
}
uint32 origCrc = Crc32::ProcessBuffer (testData);
aes.SetKey (ConstBufferPtr (testData, aes.GetKeySize()));
aes.EncryptBlocks (testData, testData.Size() / aes.GetBlockSize());
if (Crc32::ProcessBuffer (testData) != 0xb5cd5631)
throw TestFailed (SRC_POS);
aes.DecryptBlocks (testData, testData.Size() / aes.GetBlockSize());
if (origCrc != Crc32::ProcessBuffer (testData))
throw TestFailed (SRC_POS);
CipherSerpent serpent;
TestCipher (serpent, SerpentTestVectors, array_capacity (SerpentTestVectors));
CipherTwofish twofish;
TestCipher (twofish, TwofishTestVectors, array_capacity (TwofishTestVectors));
}
const EncryptionTest::XtsTestVector EncryptionTest::XtsTestVectors[] =
{
/* XTS-AES-256 */
{
// IEEE 1619 - Vector 10
{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
0,
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
},
{
0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b,
0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd,
0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0,
0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca,
0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0,
0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f,
0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec,
0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a,
0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1,
0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae,
0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29,
0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac,
0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f,
0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85,
0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa,
0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51
}
},
{
// IEEE 1619 - Vector 11
{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff },
0,
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
},
{
0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d,
0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01,
0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79,
0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a,
0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6,
0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80,
0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a,
0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0,
0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75,
0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63,
0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a,
0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68,
0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90,
0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03
}
},
{
// IEEE 1619 - Vector 12
{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff },
0,
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
},
{
0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00,
0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49,
0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8,
0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1,
0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf,
0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e,
0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6,
0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79,
0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0,
0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64,
0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d,
0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a,
0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2,
0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce,
0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36,
0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26
}
},
{
// IEEE 1619 - Vector 13
{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
0,
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
},
{
0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5,
0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1,
0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac,
0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e,
0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3,
0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5,
0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9,
0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c,
0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53,
0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7,
0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf,
0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00,
0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60,
0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55,
0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c,
0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20
}
},
{
// IEEE 1619 - Vector 14
{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
{ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff },
0,
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
},
{
0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23,
0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80,
0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04,
0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4,
0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b,
0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34,
0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8,
0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff,
0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b,
0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6,
0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa,
0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc,
0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a,
0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46,
0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde,
0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9
}
}
};
void EncryptionTest::TestXtsAES ()
{
unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE];
uint64 dataUnitNo;
size_t i;
for (i = 0; i < array_capacity (XtsTestVectors); i++)
{
AES aes;
shared_ptr <EncryptionMode> xts (new EncryptionModeXTS);
aes.SetKey (ConstBufferPtr (XtsTestVectors[i].key1, sizeof (XtsTestVectors[i].key1)));
xts->SetKey (ConstBufferPtr (XtsTestVectors[i].key2, sizeof (XtsTestVectors[i].key2)));
aes.SetMode (xts);
memcpy (p, XtsTestVectors[i].plaintext, sizeof (p));
dataUnitNo = Endian::Big (*((uint64 *) XtsTestVectors[i].dataUnitNo));
aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
aes.DecryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) == 0)
throw TestFailed (SRC_POS);
aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) != 0)
throw TestFailed (SRC_POS);
}
}
void EncryptionTest::TestXts ()
{
unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4];
unsigned int i;
uint32 crc;
uint64 unitNo;
uint64 nbrUnits;
uint64 writeOffset;
int testCase = 0;
int nTestsPerformed = 0;
static const byte testKey[] =
{
0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13
};
/* Encryption/decryption of data units (typically, volume data sectors) */
nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE;
/* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF
will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800
corresponds to the data unit 0xFFFFFFFFFF. */
for (writeOffset = 562949953420800LL;
writeOffset > 562949953420800LL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE;
writeOffset -= ENCRYPTION_DATA_UNIT_SIZE)
{
unitNo = writeOffset / ENCRYPTION_DATA_UNIT_SIZE;
// Test all EAs that support this mode of operation
foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms())
{
shared_ptr <EncryptionMode> mode (new EncryptionModeXTS);
if (!ea.IsModeSupported (mode))
continue;
ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize()));
Buffer modeKey (ea.GetKeySize());
for (size_t mi = 0; mi < modeKey.Size(); mi++)
modeKey[mi] = (byte) mi;
modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2)));
mode->SetKey (modeKey);
ea.SetMode (mode);
// Each data unit will contain the same plaintext
for (i = 0; i < nbrUnits; i++)
{
memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE,
XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext,
ENCRYPTION_DATA_UNIT_SIZE);
}
ea.EncryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE);
crc = GetCrc32 (buf, sizeof (buf));
if (typeid (ea) == typeid (AES))
{
// Verify the ciphertext of the "moving" data unit using the IEEE test vector #14
if (memcmp (XtsTestVectors[array_capacity (XtsTestVectors)-1].ciphertext,
(unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE,
ENCRYPTION_DATA_UNIT_SIZE) != 0)
{
throw TestFailed (SRC_POS);
}
// CRC of all data units in the buffer for each test case
switch (testCase)
{
case 0:
if (crc != 0x888f2990)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0xea28ea34)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0xe058f5a2)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0x10473dc9)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (Serpent))
{
switch (testCase)
{
case 0:
if (crc != 0x7edfecb3)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x357baaaa)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0xc7b9fca5)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xb5263e0c)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (Twofish))
{
switch (testCase)
{
case 0:
if (crc != 0x91525124)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x2895cc47)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0x6bee346d)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xb1c45759)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (AESTwofish))
{
switch (testCase)
{
case 0:
if (crc != 0x6cea7fa2)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x69052c4c)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0x88db8de5)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xf16fd8c5)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (AESTwofishSerpent))
{
switch (testCase)
{
case 0:
if (crc != 0xa2d7d82a)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0xdbf76412)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0xdf0ea03e)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xdadedff7)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (SerpentAES))
{
switch (testCase)
{
case 0:
if (crc != 0x6dd133b3)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x0e5717d2)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0x39f83cd9)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0x8a79fa2c)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (SerpentTwofishAES))
{
switch (testCase)
{
case 0:
if (crc != 0xe536daf8)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x3ae89e7f)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0x2cc1301a)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xcac7bdc7)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
else if (typeid (ea) == typeid (TwofishSerpent))
{
switch (testCase)
{
case 0:
if (crc != 0x2686c859)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 1:
if (crc != 0x8a201780)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 2:
if (crc != 0x8dd13796)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
case 3:
if (crc != 0xe95196cb)
throw TestFailed (SRC_POS);
nTestsPerformed++;
break;
}
}
if (crc == 0x9f5edd58)
throw TestFailed (SRC_POS);
ea.DecryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE);
if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
testCase++;
}
/* Encryption/decryption of a buffer (typically, a volume header) */
nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE;
// Test all EAs that support this mode of operation
foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms())
{
shared_ptr <EncryptionMode> mode (new EncryptionModeXTS);
if (!ea.IsModeSupported (mode))
continue;
ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize()));
Buffer modeKey (ea.GetKeySize());
for (size_t mi = 0; mi < modeKey.Size(); mi++)
modeKey[mi] = (byte) mi;
modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2)));
mode->SetKey (modeKey);
ea.SetMode (mode);
// Each data unit will contain the same plaintext
for (i = 0; i < nbrUnits; i++)
{
memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE,
XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext,
ENCRYPTION_DATA_UNIT_SIZE);
}
ea.Encrypt (buf, sizeof (buf));
crc = GetCrc32 (buf, sizeof (buf));
if (typeid (ea) == typeid (AES))
{
if (crc != 0x33b91fab)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (Serpent))
{
if (crc != 0x3494d480)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (Twofish))
{
if (crc != 0xc4d65b46)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (AESTwofish))
{
if (crc != 0x14ce7385)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (AESTwofishSerpent))
{
if (crc != 0x0ec81bf7)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (SerpentAES))
{
if (crc != 0x42f919ad)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (SerpentTwofishAES))
{
if (crc != 0x208d5c58)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
else if (typeid (ea) == typeid (TwofishSerpent))
{
if (crc != 0xbe78cec1)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
if (crc == 0x9f5edd58)
throw TestFailed (SRC_POS);
ea.Decrypt (buf, sizeof (buf));
if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58)
throw TestFailed (SRC_POS);
nTestsPerformed++;
}
if (nTestsPerformed != 80)
throw TestFailed (SRC_POS);
}
void EncryptionTest::TestPkcs5 ()
{
VolumePassword password ("password", 8);
static const byte saltData[] = { 0x12, 0x34, 0x56, 0x78 };
ConstBufferPtr salt (saltData, sizeof (saltData));
Buffer derivedKey (4);
Pkcs5HmacRipemd160 pkcs5HmacRipemd160;
pkcs5HmacRipemd160.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\x7a\x3d\x7c\x03", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha1 pkcs5HmacSha1;
pkcs5HmacSha1.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\x5c\x75\xce\xf0", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha512 pkcs5HmacSha512;
pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\x13\x64\xae\xf8", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacWhirlpool pkcs5HmacWhirlpool;
pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\x50\x7c\x36\x6f", 4) != 0)
throw TestFailed (SRC_POS);
}
}

View File

@@ -0,0 +1,50 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_EncryptionTest
#define TC_HEADER_Encryption_EncryptionTest
#include "Platform/Platform.h"
#include "Common/Crypto.h"
namespace TrueCrypt
{
class EncryptionTest
{
public:
static void TestAll ();
static void TestAll (bool enableCpuEncryptionSupport);
protected:
static void TestCiphers ();
static void TestLegacyModes ();
static void TestPkcs5 ();
static void TestXts ();
static void TestXtsAES ();
struct XtsTestVector
{
byte key1[32];
byte key2[32];
byte dataUnitNo[8];
unsigned int blockNo;
byte plaintext[ENCRYPTION_DATA_UNIT_SIZE];
byte ciphertext[ENCRYPTION_DATA_UNIT_SIZE];
};
static const XtsTestVector XtsTestVectors[];
private:
EncryptionTest ();
virtual ~EncryptionTest ();
EncryptionTest (const EncryptionTest &);
EncryptionTest &operator= (const EncryptionTest &);
};
}
#endif // TC_HEADER_Encryption_EncryptionTest

View File

@@ -0,0 +1,325 @@
/*
Copyright (c) 2008-2009 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.
*/
#ifdef TC_UNIX
# include <unistd.h>
#endif
#ifdef TC_MACOSX
# include <sys/types.h>
# include <sys/sysctl.h>
#endif
#include "Platform/SyncEvent.h"
#include "Platform/SystemLog.h"
#include "Common/Crypto.h"
#include "EncryptionThreadPool.h"
namespace TrueCrypt
{
void EncryptionThreadPool::DoWork (WorkType::Enum type, const EncryptionMode *encryptionMode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize)
{
size_t fragmentCount;
size_t unitsPerFragment;
size_t remainder;
byte *fragmentData;
uint64 fragmentStartUnitNo;
WorkItem *workItem;
WorkItem *firstFragmentWorkItem;
if (unitCount == 0)
return;
if (!ThreadPoolRunning || unitCount == 1)
{
switch (type)
{
case WorkType::DecryptDataUnits:
encryptionMode->DecryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize);
break;
case WorkType::EncryptDataUnits:
encryptionMode->EncryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize);
break;
default:
throw ParameterIncorrect (SRC_POS);
}
return;
}
if (unitCount <= ThreadCount)
{
fragmentCount = (size_t) unitCount;
unitsPerFragment = 1;
remainder = 0;
}
else
{
fragmentCount = ThreadCount;
unitsPerFragment = (size_t) unitCount / ThreadCount;
remainder = (size_t) unitCount % ThreadCount;
if (remainder > 0)
++unitsPerFragment;
}
fragmentData = data;
fragmentStartUnitNo = startUnitNo;
{
ScopeLock lock (EnqueueMutex);
firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition];
while (firstFragmentWorkItem->State != WorkItem::State::Free)
{
WorkItemCompletedEvent.Wait();
}
firstFragmentWorkItem->OutstandingFragmentCount.Set (fragmentCount);
firstFragmentWorkItem->ItemException.reset();
while (fragmentCount-- > 0)
{
workItem = &WorkItemQueue[EnqueuePosition++];
if (EnqueuePosition >= QueueSize)
EnqueuePosition = 0;
while (workItem->State != WorkItem::State::Free)
{
WorkItemCompletedEvent.Wait();
}
workItem->Type = type;
workItem->FirstFragment = firstFragmentWorkItem;
workItem->Encryption.Mode = encryptionMode;
workItem->Encryption.Data = fragmentData;
workItem->Encryption.UnitCount = unitsPerFragment;
workItem->Encryption.StartUnitNo = fragmentStartUnitNo;
workItem->Encryption.SectorSize = sectorSize;
fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE;
fragmentStartUnitNo += unitsPerFragment;
if (remainder > 0 && --remainder == 0)
--unitsPerFragment;
workItem->State.Set (WorkItem::State::Ready);
WorkItemReadyEvent.Signal();
}
}
firstFragmentWorkItem->ItemCompletedEvent.Wait();
auto_ptr <Exception> itemException;
if (firstFragmentWorkItem->ItemException.get())
itemException = firstFragmentWorkItem->ItemException;
firstFragmentWorkItem->State.Set (WorkItem::State::Free);
WorkItemCompletedEvent.Signal();
if (itemException.get())
itemException->Throw();
}
void EncryptionThreadPool::Start ()
{
if (ThreadPoolRunning)
return;
size_t cpuCount;
#ifdef TC_WINDOWS
SYSTEM_INFO sysInfo;
GetSystemInfo (&sysInfo);
cpuCount = sysInfo.dwNumberOfProcessors;
#elif defined (_SC_NPROCESSORS_ONLN)
cpuCount = (size_t) sysconf (_SC_NPROCESSORS_ONLN);
if (cpuCount == (size_t) -1)
cpuCount = 1;
#elif defined (TC_MACOSX)
int cpuCountSys;
int mib[2] = { CTL_HW, HW_NCPU };
size_t len = sizeof (cpuCountSys);
if (sysctl (mib, 2, &cpuCountSys, &len, nullptr, 0) == -1)
cpuCountSys = 1;
cpuCount = (size_t) cpuCountSys;
#else
# error Cannot determine CPU count
#endif
if (cpuCount < 2)
return;
if (cpuCount > MaxThreadCount)
cpuCount = MaxThreadCount;
StopPending = false;
DequeuePosition = 0;
EnqueuePosition = 0;
for (size_t i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i)
{
WorkItemQueue[i].State.Set (WorkItem::State::Free);
}
try
{
for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount)
{
struct ThreadFunctor : public Functor
{
virtual void operator() ()
{
WorkThreadProc();
}
};
make_shared_auto (Thread, thread);
thread->Start (new ThreadFunctor ());
RunningThreads.push_back (thread);
}
}
catch (...)
{
try
{
ThreadPoolRunning = true;
Stop();
} catch (...) { }
throw;
}
ThreadPoolRunning = true;
}
void EncryptionThreadPool::Stop ()
{
if (!ThreadPoolRunning)
return;
StopPending = true;
WorkItemReadyEvent.Signal();
foreach_ref (const Thread &thread, RunningThreads)
{
thread.Join();
}
ThreadCount = 0;
ThreadPoolRunning = false;
}
void EncryptionThreadPool::WorkThreadProc ()
{
try
{
WorkItem *workItem;
while (!StopPending)
{
{
ScopeLock lock (DequeueMutex);
workItem = &WorkItemQueue[DequeuePosition++];
if (DequeuePosition >= QueueSize)
DequeuePosition = 0;
while (!StopPending && workItem->State != WorkItem::State::Ready)
{
WorkItemReadyEvent.Wait();
}
workItem->State.Set (WorkItem::State::Busy);
}
if (StopPending)
break;
try
{
switch (workItem->Type)
{
case WorkType::DecryptDataUnits:
workItem->Encryption.Mode->DecryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize);
break;
case WorkType::EncryptDataUnits:
workItem->Encryption.Mode->EncryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize);
break;
default:
throw ParameterIncorrect (SRC_POS);
}
}
catch (Exception &e)
{
workItem->FirstFragment->ItemException.reset (e.CloneNew());
}
catch (exception &e)
{
workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
}
catch (...)
{
workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS));
}
if (workItem != workItem->FirstFragment)
{
workItem->State.Set (WorkItem::State::Free);
WorkItemCompletedEvent.Signal();
}
if (workItem->FirstFragment->OutstandingFragmentCount.Decrement() == 0)
workItem->FirstFragment->ItemCompletedEvent.Signal();
}
}
catch (exception &e)
{
SystemLog::WriteException (e);
}
catch (...)
{
SystemLog::WriteException (UnknownException (SRC_POS));
}
}
volatile bool EncryptionThreadPool::ThreadPoolRunning = false;
volatile bool EncryptionThreadPool::StopPending = false;
size_t EncryptionThreadPool::ThreadCount;
EncryptionThreadPool::WorkItem EncryptionThreadPool::WorkItemQueue[QueueSize];
volatile size_t EncryptionThreadPool::EnqueuePosition;
volatile size_t EncryptionThreadPool::DequeuePosition;
Mutex EncryptionThreadPool::EnqueueMutex;
Mutex EncryptionThreadPool::DequeueMutex;
SyncEvent EncryptionThreadPool::WorkItemReadyEvent;
SyncEvent EncryptionThreadPool::WorkItemCompletedEvent;
list < shared_ptr <Thread> > EncryptionThreadPool::RunningThreads;
}

View File

@@ -0,0 +1,87 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_EncryptionThreadPool
#define TC_HEADER_Volume_EncryptionThreadPool
#include "Platform/Platform.h"
#include "EncryptionMode.h"
namespace TrueCrypt
{
class EncryptionThreadPool
{
public:
struct WorkType
{
enum Enum
{
EncryptDataUnits,
DecryptDataUnits,
DeriveKey
};
};
struct WorkItem
{
struct State
{
enum Enum
{
Free,
Ready,
Busy
};
};
struct WorkItem *FirstFragment;
auto_ptr <Exception> ItemException;
SyncEvent ItemCompletedEvent;
SharedVal <size_t> OutstandingFragmentCount;
SharedVal <State::Enum> State;
WorkType::Enum Type;
union
{
struct
{
const EncryptionMode *Mode;
byte *Data;
uint64 StartUnitNo;
uint64 UnitCount;
size_t SectorSize;
} Encryption;
};
};
static void DoWork (WorkType::Enum type, const EncryptionMode *mode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize);
static bool IsRunning () { return ThreadPoolRunning; }
static void Start ();
static void Stop ();
protected:
static void WorkThreadProc ();
static const size_t MaxThreadCount = 32;
static const size_t QueueSize = MaxThreadCount * 2;
static Mutex DequeueMutex;
static volatile size_t DequeuePosition;
static volatile size_t EnqueuePosition;
static Mutex EnqueueMutex;
static list < shared_ptr <Thread> > RunningThreads;
static volatile bool StopPending;
static size_t ThreadCount;
static volatile bool ThreadPoolRunning;
static SyncEvent WorkItemCompletedEvent;
static WorkItem WorkItemQueue[QueueSize];
static SyncEvent WorkItemReadyEvent;
};
}
#endif // TC_HEADER_Volume_EncryptionThreadPool

138
src/Volume/Hash.cpp Normal file
View File

@@ -0,0 +1,138 @@
/*
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 "Hash.h"
#include "Crypto/Rmd160.h"
#include "Crypto/Sha1.h"
#include "Crypto/Sha2.h"
#include "Crypto/Whirlpool.h"
namespace TrueCrypt
{
HashList Hash::GetAvailableAlgorithms ()
{
HashList l;
l.push_back (shared_ptr <Hash> (new Ripemd160 ()));
l.push_back (shared_ptr <Hash> (new Sha512 ()));
l.push_back (shared_ptr <Hash> (new Whirlpool ()));
l.push_back (shared_ptr <Hash> (new Sha1 ()));
return l;
}
void Hash::ValidateDataParameters (const ConstBufferPtr &data) const
{
if (data.Size() < 1)
throw ParameterIncorrect (SRC_POS);
}
void Hash::ValidateDigestParameters (const BufferPtr &buffer) const
{
if (buffer.Size() != GetDigestSize ())
throw ParameterIncorrect (SRC_POS);
}
// RIPEMD-160
Ripemd160::Ripemd160 ()
{
Context.Allocate (sizeof (RMD160_CTX));
Init();
}
void Ripemd160::GetDigest (const BufferPtr &buffer)
{
if_debug (ValidateDigestParameters (buffer));
RMD160Final (buffer, (RMD160_CTX *) Context.Ptr());
}
void Ripemd160::Init ()
{
RMD160Init ((RMD160_CTX *) Context.Ptr());
}
void Ripemd160::ProcessData (const ConstBufferPtr &data)
{
if_debug (ValidateDataParameters (data));
RMD160Update ((RMD160_CTX *) Context.Ptr(), data.Get(), (int) data.Size());
}
// SHA-1
Sha1::Sha1 ()
{
Deprecated = true;
Context.Allocate (sizeof (sha1_ctx));
Init();
}
void Sha1::GetDigest (const BufferPtr &buffer)
{
if_debug (ValidateDigestParameters (buffer));
sha1_end (buffer, (sha1_ctx *) Context.Ptr());
}
void Sha1::Init ()
{
sha1_begin ((sha1_ctx *) Context.Ptr());
}
void Sha1::ProcessData (const ConstBufferPtr &data)
{
if_debug (ValidateDataParameters (data));
sha1_hash (data.Get(), (int) data.Size(), (sha1_ctx *) Context.Ptr());
}
// SHA-512
Sha512::Sha512 ()
{
Context.Allocate (sizeof (sha512_ctx));
Init();
}
void Sha512::GetDigest (const BufferPtr &buffer)
{
if_debug (ValidateDigestParameters (buffer));
sha512_end (buffer, (sha512_ctx *) Context.Ptr());
}
void Sha512::Init ()
{
sha512_begin ((sha512_ctx *) Context.Ptr());
}
void Sha512::ProcessData (const ConstBufferPtr &data)
{
if_debug (ValidateDataParameters (data));
sha512_hash (data.Get(), (int) data.Size(), (sha512_ctx *) Context.Ptr());
}
// Whirlpool
Whirlpool::Whirlpool ()
{
Context.Allocate (sizeof (WHIRLPOOL_CTX));
Init();
}
void Whirlpool::GetDigest (const BufferPtr &buffer)
{
if_debug (ValidateDigestParameters (buffer));
WHIRLPOOL_finalize ((WHIRLPOOL_CTX *) Context.Ptr(), buffer);
}
void Whirlpool::Init ()
{
WHIRLPOOL_init ((WHIRLPOOL_CTX *) Context.Ptr());
}
void Whirlpool::ProcessData (const ConstBufferPtr &data)
{
if_debug (ValidateDataParameters (data));
WHIRLPOOL_add (data.Get(), (int) data.Size() * 8, (WHIRLPOOL_CTX *) Context.Ptr());
}
}

135
src/Volume/Hash.h Normal file
View File

@@ -0,0 +1,135 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_Hash
#define TC_HEADER_Encryption_Hash
#include "Platform/Platform.h"
namespace TrueCrypt
{
class Hash;
typedef list < shared_ptr <Hash> > HashList;
class Hash
{
public:
Hash () : Deprecated (false) { }
virtual ~Hash () { }
static HashList GetAvailableAlgorithms ();
virtual void GetDigest (const BufferPtr &buffer) = 0;
virtual size_t GetBlockSize () const = 0;
virtual size_t GetDigestSize () const = 0;
virtual wstring GetName () const = 0;
virtual shared_ptr <Hash> GetNew () const = 0;
virtual void Init () = 0;
bool IsDeprecated () const { return Deprecated; }
virtual void ProcessData (const ConstBufferPtr &data) = 0;
virtual void ValidateDataParameters (const ConstBufferPtr &data) const;
virtual void ValidateDigestParameters (const BufferPtr &buffer) const;
protected:
SecureBuffer Context;
bool Deprecated;
private:
Hash (const Hash &);
Hash &operator= (const Hash &);
};
// RIPEMD-160
class Ripemd160 : public Hash
{
public:
Ripemd160 ();
virtual ~Ripemd160 () { }
virtual void GetDigest (const BufferPtr &buffer);
virtual size_t GetBlockSize () const { return 64; }
virtual size_t GetDigestSize () const { return 160 / 8; }
virtual wstring GetName () const { return L"RIPEMD-160"; }
virtual shared_ptr <Hash> GetNew () const { return shared_ptr <Hash> (new Ripemd160); }
virtual void Init ();
virtual void ProcessData (const ConstBufferPtr &data);
protected:
private:
Ripemd160 (const Ripemd160 &);
Ripemd160 &operator= (const Ripemd160 &);
};
// SHA-1
class Sha1 : public Hash
{
public:
Sha1 ();
virtual ~Sha1 () { }
virtual void GetDigest (const BufferPtr &buffer);
virtual size_t GetBlockSize () const { return 64; }
virtual size_t GetDigestSize () const { return 160 / 8; }
virtual wstring GetName () const { return L"SHA-1"; }
virtual shared_ptr <Hash> GetNew () const { return shared_ptr <Hash> (new Sha1); }
virtual void Init ();
virtual void ProcessData (const ConstBufferPtr &data);
protected:
private:
Sha1 (const Sha1 &);
Sha1 &operator= (const Sha1 &);
};
// SHA-512
class Sha512 : public Hash
{
public:
Sha512 ();
virtual ~Sha512 () { }
virtual void GetDigest (const BufferPtr &buffer);
virtual size_t GetBlockSize () const { return 128; }
virtual size_t GetDigestSize () const { return 512 / 8; }
virtual wstring GetName () const { return L"SHA-512"; }
virtual shared_ptr <Hash> GetNew () const { return shared_ptr <Hash> (new Sha512); }
virtual void Init ();
virtual void ProcessData (const ConstBufferPtr &data);
protected:
private:
Sha512 (const Sha512 &);
Sha512 &operator= (const Sha512 &);
};
// Whirlpool
class Whirlpool : public Hash
{
public:
Whirlpool ();
virtual ~Whirlpool () { }
virtual void GetDigest (const BufferPtr &buffer);
virtual size_t GetBlockSize () const { return 64; }
virtual size_t GetDigestSize () const { return 512 / 8; }
virtual wstring GetName () const { return L"Whirlpool"; }
virtual shared_ptr <Hash> GetNew () const { return shared_ptr <Hash> (new Whirlpool); }
virtual void Init ();
virtual void ProcessData (const ConstBufferPtr &data);
protected:
private:
Whirlpool (const Whirlpool &);
Whirlpool &operator= (const Whirlpool &);
};
}
#endif // TC_HEADER_Encryption_Hash

181
src/Volume/Keyfile.cpp Normal file
View File

@@ -0,0 +1,181 @@
/*
Copyright (c) 2008-2009 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/Serializer.h"
#include "Common/SecurityToken.h"
#include "Crc32.h"
#include "Keyfile.h"
#include "VolumeException.h"
namespace TrueCrypt
{
void Keyfile::Apply (const BufferPtr &pool) const
{
if (Path.IsDirectory())
throw ParameterIncorrect (SRC_POS);
File file;
Crc32 crc32;
size_t poolPos = 0;
uint64 totalLength = 0;
uint64 readLength;
SecureBuffer keyfileBuf (File::GetOptimalReadSize());
if (SecurityToken::IsKeyfilePathValid (Path))
{
// Apply keyfile generated by a security token
vector <byte> keyfileData;
SecurityToken::GetKeyfileData (SecurityTokenKeyfile (wstring (Path)), keyfileData);
if (keyfileData.size() < MinProcessedLength)
throw InsufficientData (SRC_POS, Path);
for (size_t i = 0; i < keyfileData.size(); i++)
{
uint32 crc = crc32.Process (keyfileData[i]);
pool[poolPos++] += (byte) (crc >> 24);
pool[poolPos++] += (byte) (crc >> 16);
pool[poolPos++] += (byte) (crc >> 8);
pool[poolPos++] += (byte) crc;
if (poolPos >= pool.Size())
poolPos = 0;
if (++totalLength >= MaxProcessedLength)
break;
}
Memory::Erase (&keyfileData.front(), keyfileData.size());
goto done;
}
file.Open (Path, File::OpenRead, File::ShareRead);
while ((readLength = file.Read (keyfileBuf)) > 0)
{
for (size_t i = 0; i < readLength; i++)
{
uint32 crc = crc32.Process (keyfileBuf[i]);
pool[poolPos++] += (byte) (crc >> 24);
pool[poolPos++] += (byte) (crc >> 16);
pool[poolPos++] += (byte) (crc >> 8);
pool[poolPos++] += (byte) crc;
if (poolPos >= pool.Size())
poolPos = 0;
if (++totalLength >= MaxProcessedLength)
goto done;
}
}
done:
if (totalLength < MinProcessedLength)
throw InsufficientData (SRC_POS, Path);
}
shared_ptr <VolumePassword> Keyfile::ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password)
{
if (!password)
password.reset (new VolumePassword);
if (!keyfiles || keyfiles->size() < 1)
return password;
KeyfileList keyfilesExp;
HiddenFileWasPresentInKeyfilePath = false;
// Enumerate directories
foreach (shared_ptr <Keyfile> keyfile, *keyfiles)
{
if (FilesystemPath (*keyfile).IsDirectory())
{
size_t keyfileCount = 0;
foreach_ref (const FilePath &path, Directory::GetFilePaths (*keyfile))
{
#ifdef TC_UNIX
// Skip hidden files
if (wstring (path.ToBaseName()).find (L'.') == 0)
{
HiddenFileWasPresentInKeyfilePath = true;
continue;
}
#endif
keyfilesExp.push_back (make_shared <Keyfile> (path));
++keyfileCount;
}
if (keyfileCount == 0)
throw KeyfilePathEmpty (SRC_POS, FilesystemPath (*keyfile));
}
else
{
keyfilesExp.push_back (keyfile);
}
}
make_shared_auto (VolumePassword, newPassword);
if (keyfilesExp.size() < 1)
{
newPassword->Set (*password);
}
else
{
SecureBuffer keyfilePool (VolumePassword::MaxSize);
// Pad password with zeros if shorter than max length
keyfilePool.Zero();
keyfilePool.CopyFrom (ConstBufferPtr (password->DataPtr(), password->Size()));
// Apply all keyfiles
foreach_ref (const Keyfile &k, keyfilesExp)
{
k.Apply (keyfilePool);
}
newPassword->Set (keyfilePool);
}
return newPassword;
}
shared_ptr <KeyfileList> Keyfile::DeserializeList (shared_ptr <Stream> stream, const string &name)
{
shared_ptr <KeyfileList> keyfiles;
Serializer sr (stream);
if (!sr.DeserializeBool (name + "Null"))
{
keyfiles.reset (new KeyfileList);
foreach (const wstring &k, sr.DeserializeWStringList (name))
keyfiles->push_back (make_shared <Keyfile> (k));
}
return keyfiles;
}
void Keyfile::SerializeList (shared_ptr <Stream> stream, const string &name, shared_ptr <KeyfileList> keyfiles)
{
Serializer sr (stream);
sr.Serialize (name + "Null", keyfiles == nullptr);
if (keyfiles)
{
list <wstring> sl;
foreach_ref (const Keyfile &k, *keyfiles)
sl.push_back (FilesystemPath (k));
sr.Serialize (name, sl);
}
}
bool Keyfile::HiddenFileWasPresentInKeyfilePath = false;
}

49
src/Volume/Keyfile.h Normal file
View File

@@ -0,0 +1,49 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_Keyfile
#define TC_HEADER_Encryption_Keyfile
#include "Platform/Platform.h"
#include "Platform/Stream.h"
#include "VolumePassword.h"
namespace TrueCrypt
{
class Keyfile;
typedef list < shared_ptr <Keyfile> > KeyfileList;
class Keyfile
{
public:
Keyfile (const FilesystemPath &path) : Path (path) { }
virtual ~Keyfile () { };
operator FilesystemPath () const { return Path; }
static shared_ptr <VolumePassword> ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password);
static shared_ptr <KeyfileList> DeserializeList (shared_ptr <Stream> stream, const string &name);
static void SerializeList (shared_ptr <Stream> stream, const string &name, shared_ptr <KeyfileList> keyfiles);
static bool WasHiddenFilePresentInKeyfilePath() { bool r = HiddenFileWasPresentInKeyfilePath; HiddenFileWasPresentInKeyfilePath = false; return r; }
static const size_t MinProcessedLength = 1;
static const size_t MaxProcessedLength = 1024 * 1024;
protected:
void Apply (const BufferPtr &pool) const;
static bool HiddenFileWasPresentInKeyfilePath;
FilesystemPath Path;
private:
Keyfile (const Keyfile &);
Keyfile &operator= (const Keyfile &);
};
}
#endif // TC_HEADER_Encryption_Keyfile

96
src/Volume/Pkcs5Kdf.cpp Normal file
View File

@@ -0,0 +1,96 @@
/*
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 "Common/Pkcs5.h"
#include "Pkcs5Kdf.h"
#include "VolumePassword.h"
namespace TrueCrypt
{
Pkcs5Kdf::Pkcs5Kdf ()
{
}
Pkcs5Kdf::~Pkcs5Kdf ()
{
}
void Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const
{
DeriveKey (key, password, salt, GetIterationCount());
}
shared_ptr <Pkcs5Kdf> Pkcs5Kdf::GetAlgorithm (const wstring &name)
{
foreach (shared_ptr <Pkcs5Kdf> kdf, GetAvailableAlgorithms())
{
if (kdf->GetName() == name)
return kdf;
}
throw ParameterIncorrect (SRC_POS);
}
shared_ptr <Pkcs5Kdf> Pkcs5Kdf::GetAlgorithm (const Hash &hash)
{
foreach (shared_ptr <Pkcs5Kdf> kdf, GetAvailableAlgorithms())
{
if (typeid (*kdf->GetHash()) == typeid (hash))
return kdf;
}
throw ParameterIncorrect (SRC_POS);
}
Pkcs5KdfList Pkcs5Kdf::GetAvailableAlgorithms ()
{
Pkcs5KdfList l;
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacRipemd160 ()));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacSha512 ()));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacWhirlpool ()));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacSha1 ()));
return l;
}
void Pkcs5Kdf::ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
if (key.Size() < 1 || password.Size() < 1 || salt.Size() < 1 || iterationCount < 1)
throw ParameterIncorrect (SRC_POS);
}
void Pkcs5HmacRipemd160::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacRipemd160_1000::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacSha1::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_sha1 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacSha512::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_sha512 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacWhirlpool::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_whirlpool ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
}

127
src/Volume/Pkcs5Kdf.h Normal file
View File

@@ -0,0 +1,127 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_Pkcs5
#define TC_HEADER_Encryption_Pkcs5
#include "Platform/Platform.h"
#include "Hash.h"
#include "VolumePassword.h"
namespace TrueCrypt
{
class Pkcs5Kdf;
typedef list < shared_ptr <Pkcs5Kdf> > Pkcs5KdfList;
class Pkcs5Kdf
{
public:
virtual ~Pkcs5Kdf ();
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const;
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const = 0;
static shared_ptr <Pkcs5Kdf> GetAlgorithm (const wstring &name);
static shared_ptr <Pkcs5Kdf> GetAlgorithm (const Hash &hash);
static Pkcs5KdfList GetAvailableAlgorithms ();
virtual shared_ptr <Hash> GetHash () const = 0;
virtual int GetIterationCount () const = 0;
virtual wstring GetName () const = 0;
virtual bool IsDeprecated () const { return GetHash()->IsDeprecated(); }
protected:
Pkcs5Kdf ();
void ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
private:
Pkcs5Kdf (const Pkcs5Kdf &);
Pkcs5Kdf &operator= (const Pkcs5Kdf &);
};
class Pkcs5HmacRipemd160 : public Pkcs5Kdf
{
public:
Pkcs5HmacRipemd160 () { }
virtual ~Pkcs5HmacRipemd160 () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Ripemd160); }
virtual int GetIterationCount () const { return 2000; }
virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; }
private:
Pkcs5HmacRipemd160 (const Pkcs5HmacRipemd160 &);
Pkcs5HmacRipemd160 &operator= (const Pkcs5HmacRipemd160 &);
};
class Pkcs5HmacRipemd160_1000 : public Pkcs5Kdf
{
public:
Pkcs5HmacRipemd160_1000 () { }
virtual ~Pkcs5HmacRipemd160_1000 () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Ripemd160); }
virtual int GetIterationCount () const { return 1000; }
virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; }
private:
Pkcs5HmacRipemd160_1000 (const Pkcs5HmacRipemd160_1000 &);
Pkcs5HmacRipemd160_1000 &operator= (const Pkcs5HmacRipemd160_1000 &);
};
class Pkcs5HmacSha1 : public Pkcs5Kdf
{
public:
Pkcs5HmacSha1 () { }
virtual ~Pkcs5HmacSha1 () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Sha1); }
virtual int GetIterationCount () const { return 2000; }
virtual wstring GetName () const { return L"HMAC-SHA-1"; }
private:
Pkcs5HmacSha1 (const Pkcs5HmacSha1 &);
Pkcs5HmacSha1 &operator= (const Pkcs5HmacSha1 &);
};
class Pkcs5HmacSha512 : public Pkcs5Kdf
{
public:
Pkcs5HmacSha512 () { }
virtual ~Pkcs5HmacSha512 () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Sha512); }
virtual int GetIterationCount () const { return 1000; }
virtual wstring GetName () const { return L"HMAC-SHA-512"; }
private:
Pkcs5HmacSha512 (const Pkcs5HmacSha512 &);
Pkcs5HmacSha512 &operator= (const Pkcs5HmacSha512 &);
};
class Pkcs5HmacWhirlpool : public Pkcs5Kdf
{
public:
Pkcs5HmacWhirlpool () { }
virtual ~Pkcs5HmacWhirlpool () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Whirlpool); }
virtual int GetIterationCount () const { return 1000; }
virtual wstring GetName () const { return L"HMAC-Whirlpool"; }
private:
Pkcs5HmacWhirlpool (const Pkcs5HmacWhirlpool &);
Pkcs5HmacWhirlpool &operator= (const Pkcs5HmacWhirlpool &);
};
}
#endif // TC_HEADER_Encryption_Pkcs5

25
src/Volume/Version.h Normal file
View File

@@ -0,0 +1,25 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_Version
#define TC_HEADER_Volume_Version
#include "Platform/PlatformBase.h"
#include "Common/Tcdefs.h"
namespace TrueCrypt
{
class Version
{
public:
static const string String () { return VERSION_STRING; }
static const uint16 Number () { return VERSION_NUM; }
};
}
#endif // TC_HEADER_Volume_Version

388
src/Volume/Volume.cpp Normal file
View File

@@ -0,0 +1,388 @@
/*
Copyright (c) 2008-2010 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.
*/
#ifndef TC_WINDOWS
#include <errno.h>
#endif
#include "EncryptionModeLRW.h"
#include "EncryptionModeXTS.h"
#include "Volume.h"
#include "VolumeHeader.h"
#include "VolumeLayout.h"
#include "Common/Crypto.h"
namespace TrueCrypt
{
Volume::Volume ()
: HiddenVolumeProtectionTriggered (false),
SystemEncryption (false),
VolumeDataSize (0),
TopWriteOffset (0),
TotalDataRead (0),
TotalDataWritten (0)
{
}
Volume::~Volume ()
{
}
void Volume::CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength)
{
uint64 writeHostEndOffset = writeHostOffset + writeLength - 1;
if ((writeHostOffset < ProtectedRangeStart) ? (writeHostEndOffset >= ProtectedRangeStart) : (writeHostOffset <= ProtectedRangeEnd - 1))
{
HiddenVolumeProtectionTriggered = true;
throw VolumeProtected (SRC_POS);
}
}
void Volume::Close ()
{
if (VolumeFile.get() == nullptr)
throw NotInitialized (SRC_POS);
VolumeFile.reset();
}
shared_ptr <EncryptionAlgorithm> Volume::GetEncryptionAlgorithm () const
{
if_debug (ValidateState ());
return EA;
}
shared_ptr <EncryptionMode> Volume::GetEncryptionMode () const
{
if_debug (ValidateState ());
return EA->GetMode();
}
void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope)
{
make_shared_auto (File, file);
File::FileOpenFlags flags = (preserveTimestamps ? File::PreserveTimestamps : File::FlagsNone);
try
{
if (protection == VolumeProtection::ReadOnly)
file->Open (volumePath, File::OpenRead, File::ShareRead, flags);
else
file->Open (volumePath, File::OpenReadWrite, File::ShareNone, flags);
}
catch (SystemException &e)
{
if (e.GetErrorCode() ==
#ifdef TC_WINDOWS
ERROR_SHARING_VIOLATION)
#else
EAGAIN)
#endif
{
if (!sharedAccessAllowed)
throw VolumeHostInUse (SRC_POS);
file->Open (volumePath, protection == VolumeProtection::ReadOnly ? File::OpenRead : File::OpenReadWrite, File::ShareReadWriteIgnoreLock, flags);
}
else
throw;
}
return Open (file, password, keyfiles, protection, protectionPassword, protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope);
}
void Volume::Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, shared_ptr <KeyfileList> protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope)
{
if (!volumeFile)
throw ParameterIncorrect (SRC_POS);
Protection = protection;
VolumeFile = volumeFile;
SystemEncryption = partitionInSystemEncryptionScope;
try
{
VolumeHostSize = VolumeFile->Length();
shared_ptr <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (keyfiles, password);
bool skipLayoutV1Normal = false;
bool deviceHosted = GetPath().IsDevice();
size_t hostDeviceSectorSize = 0;
if (deviceHosted)
hostDeviceSectorSize = volumeFile->GetDeviceSectorSize();
// Test volume layouts
foreach (shared_ptr <VolumeLayout> layout, VolumeLayout::GetAvailableLayouts (volumeType))
{
if (skipLayoutV1Normal && typeid (*layout) == typeid (VolumeLayoutV1Normal))
{
// Skip VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal
continue;
}
if (useBackupHeaders && !layout->HasBackupHeader())
continue;
if (typeid (*layout) == typeid (VolumeLayoutV1Hidden)
&& deviceHosted
&& hostDeviceSectorSize != TC_SECTOR_SIZE_LEGACY)
{
continue;
}
SecureBuffer headerBuffer (layout->GetHeaderSize());
if (layout->HasDriveHeader())
{
if (!partitionInSystemEncryptionScope)
continue;
if (!GetPath().IsDevice())
throw PartitionDeviceRequired (SRC_POS);
File driveDevice;
driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition());
int headerOffset = layout->GetHeaderOffset();
if (headerOffset >= 0)
driveDevice.SeekAt (headerOffset);
else
driveDevice.SeekEnd (headerOffset);
if (driveDevice.Read (headerBuffer) != layout->GetHeaderSize())
continue;
}
else
{
if (partitionInSystemEncryptionScope)
continue;
int headerOffset = useBackupHeaders ? layout->GetBackupHeaderOffset() : layout->GetHeaderOffset();
if (headerOffset >= 0)
VolumeFile->SeekAt (headerOffset);
else
VolumeFile->SeekEnd (headerOffset);
if (VolumeFile->Read (headerBuffer) != layout->GetHeaderSize())
continue;
}
EncryptionAlgorithmList layoutEncryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms();
EncryptionModeList layoutEncryptionModes = layout->GetSupportedEncryptionModes();
if (typeid (*layout) == typeid (VolumeLayoutV2Normal))
{
skipLayoutV1Normal = true;
// Test all algorithms and modes of VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal
layoutEncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms();
layoutEncryptionModes = EncryptionMode::GetAvailableModes();
}
shared_ptr <VolumeHeader> header = layout->GetHeader();
if (header->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layoutEncryptionAlgorithms, layoutEncryptionModes))
{
// Header decrypted
if (typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x600)
{
// VolumeLayoutV1Normal has been opened as VolumeLayoutV2Normal
layout.reset (new VolumeLayoutV1Normal);
header->SetSize (layout->GetHeaderSize());
layout->SetHeader (header);
}
Type = layout->GetType();
SectorSize = header->GetSectorSize();
VolumeDataOffset = layout->GetDataOffset (VolumeHostSize);
VolumeDataSize = layout->GetDataSize (VolumeHostSize);
Header = header;
Layout = layout;
EA = header->GetEncryptionAlgorithm();
EncryptionMode &mode = *EA->GetMode();
if (layout->HasDriveHeader())
{
if (header->GetEncryptedAreaLength() != header->GetVolumeDataSize())
throw VolumeEncryptionNotCompleted (SRC_POS);
uint64 partitionStartOffset = VolumeFile->GetPartitionDeviceStartOffset();
if (partitionStartOffset < header->GetEncryptedAreaStart()
|| partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength())
throw PasswordIncorrect (SRC_POS);
mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE);
}
else if (typeid (mode) == typeid (EncryptionModeLRW))
{
mode.SetSectorOffset (VolumeDataOffset / SectorSize);
}
// Volume protection
if (Protection == VolumeProtection::HiddenVolumeReadOnly)
{
if (Type == VolumeType::Hidden)
throw PasswordIncorrect (SRC_POS);
else
{
try
{
Volume protectedVolume;
protectedVolume.Open (VolumeFile,
protectionPassword, protectionKeyfiles,
VolumeProtection::ReadOnly,
shared_ptr <VolumePassword> (), shared_ptr <KeyfileList> (),
VolumeType::Hidden,
useBackupHeaders);
if (protectedVolume.GetType() != VolumeType::Hidden)
ParameterIncorrect (SRC_POS);
ProtectedRangeStart = protectedVolume.VolumeDataOffset;
ProtectedRangeEnd = protectedVolume.VolumeDataOffset + protectedVolume.VolumeDataSize;
if (typeid (*protectedVolume.Layout) == typeid (VolumeLayoutV1Hidden))
ProtectedRangeEnd += protectedVolume.Layout->GetHeaderSize();
}
catch (PasswordException&)
{
if (protectionKeyfiles && !protectionKeyfiles->empty())
throw ProtectionPasswordKeyfilesIncorrect (SRC_POS);
throw ProtectionPasswordIncorrect (SRC_POS);
}
}
}
return;
}
}
if (partitionInSystemEncryptionScope)
throw PasswordOrKeyboardLayoutIncorrect (SRC_POS);
if (!partitionInSystemEncryptionScope && GetPath().IsDevice())
{
// Check if the device contains TrueCrypt Boot Loader
try
{
File driveDevice;
driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition());
Buffer mbr (VolumeFile->GetDeviceSectorSize());
driveDevice.ReadAt (mbr, 0);
// Search for the string "TrueCrypt"
size_t nameLen = strlen (TC_APP_NAME);
for (size_t i = 0; i < mbr.Size() - nameLen; ++i)
{
if (memcmp (mbr.Ptr() + i, TC_APP_NAME, nameLen) == 0)
throw PasswordOrMountOptionsIncorrect (SRC_POS);
}
}
catch (PasswordOrMountOptionsIncorrect&) { throw; }
catch (...) { }
}
if (keyfiles && !keyfiles->empty())
throw PasswordKeyfilesIncorrect (SRC_POS);
throw PasswordIncorrect (SRC_POS);
}
catch (...)
{
Close();
throw;
}
}
void Volume::ReadSectors (const BufferPtr &buffer, uint64 byteOffset)
{
if_debug (ValidateState ());
uint64 length = buffer.Size();
uint64 hostOffset = VolumeDataOffset + byteOffset;
if (length % SectorSize != 0 || byteOffset % SectorSize != 0)
throw ParameterIncorrect (SRC_POS);
if (VolumeFile->ReadAt (buffer, hostOffset) != length)
throw MissingVolumeData (SRC_POS);
EA->DecryptSectors (buffer, hostOffset / SectorSize, length / SectorSize, SectorSize);
TotalDataRead += length;
}
void Volume::ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf)
{
if_debug (ValidateState ());
if (Protection == VolumeProtection::ReadOnly)
throw VolumeReadOnly (SRC_POS);
SecureBuffer newHeaderBuffer (Layout->GetHeaderSize());
Header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, newPkcs5Kdf);
int headerOffset = backupHeader ? Layout->GetBackupHeaderOffset() : Layout->GetHeaderOffset();
if (headerOffset >= 0)
VolumeFile->SeekAt (headerOffset);
else
VolumeFile->SeekEnd (headerOffset);
VolumeFile->Write (newHeaderBuffer);
}
void Volume::ValidateState () const
{
if (VolumeFile.get() == nullptr)
throw NotInitialized (SRC_POS);
}
void Volume::WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset)
{
if_debug (ValidateState ());
uint64 length = buffer.Size();
uint64 hostOffset = VolumeDataOffset + byteOffset;
if (length % SectorSize != 0
|| byteOffset % SectorSize != 0
|| byteOffset + length > VolumeDataSize)
throw ParameterIncorrect (SRC_POS);
if (Protection == VolumeProtection::ReadOnly)
throw VolumeReadOnly (SRC_POS);
if (HiddenVolumeProtectionTriggered)
throw VolumeProtected (SRC_POS);
if (Protection == VolumeProtection::HiddenVolumeReadOnly)
CheckProtectedRange (hostOffset, length);
SecureBuffer encBuf (buffer.Size());
encBuf.CopyFrom (buffer);
EA->EncryptSectors (encBuf, hostOffset / SectorSize, length / SectorSize, SectorSize);
VolumeFile->WriteAt (encBuf, hostOffset);
TotalDataWritten += length;
uint64 writeEndOffset = byteOffset + buffer.Size();
if (writeEndOffset > TopWriteOffset)
TopWriteOffset = writeEndOffset;
}
}

126
src/Volume/Volume.h Normal file
View File

@@ -0,0 +1,126 @@
/*
Copyright (c) 2008-2009 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.
*/
#ifndef TC_HEADER_Volume_Volume
#define TC_HEADER_Volume_Volume
#include "Platform/Platform.h"
#include "Platform/StringConverter.h"
#include "EncryptionAlgorithm.h"
#include "EncryptionMode.h"
#include "Keyfile.h"
#include "VolumePassword.h"
#include "VolumeException.h"
#include "VolumeLayout.h"
namespace TrueCrypt
{
class VolumePath
{
public:
VolumePath () { }
VolumePath (const wstring &path) { Data = path; }
VolumePath (const FilesystemPath &path) { Data = path; }
bool operator== (const VolumePath &other) const { return Data == other.Data; }
bool operator!= (const VolumePath &other) const { return Data != other.Data; }
operator FilesystemPath () const { return FilesystemPath (Data); }
operator string () const { return StringConverter::ToSingle (Data); }
operator wstring () const { return Data; }
bool IsDevice () const { return FilesystemPath (Data).IsBlockDevice() || FilesystemPath (Data).IsCharacterDevice(); }
bool IsEmpty () const { return Data.empty(); }
protected:
wstring Data;
};
typedef list <VolumePath> VolumePathList;
struct VolumeHostType
{
enum Enum
{
Unknown,
File,
Device
};
};
struct VolumeProtection
{
enum Enum
{
None,
ReadOnly,
HiddenVolumeReadOnly
};
};
class Volume
{
public:
Volume ();
virtual ~Volume ();
void Close ();
shared_ptr <EncryptionAlgorithm> GetEncryptionAlgorithm () const;
shared_ptr <EncryptionMode> GetEncryptionMode () const;
shared_ptr <File> GetFile () const { return VolumeFile; }
shared_ptr <VolumeHeader> GetHeader () const { return Header; }
uint64 GetHeaderCreationTime () const { return Header->GetHeaderCreationTime(); }
uint64 GetHostSize () const { return VolumeHostSize; }
shared_ptr <VolumeLayout> GetLayout () const { return Layout; }
VolumePath GetPath () const { return VolumeFile->GetPath(); }
VolumeProtection::Enum GetProtectionType () const { return Protection; }
shared_ptr <Pkcs5Kdf> GetPkcs5Kdf () const { return Header->GetPkcs5Kdf(); }
uint32 GetSaltSize () const { return Header->GetSaltSize(); }
size_t GetSectorSize () const { return SectorSize; }
uint64 GetSize () const { return VolumeDataSize; }
uint64 GetTopWriteOffset () const { return TopWriteOffset; }
uint64 GetTotalDataRead () const { return TotalDataRead; }
uint64 GetTotalDataWritten () const { return TotalDataWritten; }
VolumeType::Enum GetType () const { return Type; }
uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); }
bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; }
bool IsInSystemEncryptionScope () const { return SystemEncryption; }
void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void ReadSectors (const BufferPtr &buffer, uint64 byteOffset);
void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf);
void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset);
protected:
void CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength);
void ValidateState () const;
shared_ptr <EncryptionAlgorithm> EA;
shared_ptr <VolumeHeader> Header;
bool HiddenVolumeProtectionTriggered;
shared_ptr <VolumeLayout> Layout;
uint64 ProtectedRangeStart;
uint64 ProtectedRangeEnd;
VolumeProtection::Enum Protection;
size_t SectorSize;
bool SystemEncryption;
VolumeType::Enum Type;
shared_ptr <File> VolumeFile;
uint64 VolumeHostSize;
uint64 VolumeDataOffset;
uint64 VolumeDataSize;
uint64 TopWriteOffset;
uint64 TotalDataRead;
uint64 TotalDataWritten;
private:
Volume (const Volume &);
Volume &operator= (const Volume &);
};
}
#endif // TC_HEADER_Volume_Volume

62
src/Volume/Volume.make Normal file
View File

@@ -0,0 +1,62 @@
#
# Copyright (c) 2008-2010 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.
#
OBJS :=
OBJS += Cipher.o
OBJS += EncryptionAlgorithm.o
OBJS += EncryptionMode.o
OBJS += EncryptionModeCBC.o
OBJS += EncryptionModeLRW.o
OBJS += EncryptionModeXTS.o
OBJS += EncryptionTest.o
OBJS += EncryptionThreadPool.o
OBJS += Hash.o
OBJS += Keyfile.o
OBJS += Pkcs5Kdf.o
OBJS += Volume.o
OBJS += VolumeException.o
OBJS += VolumeHeader.o
OBJS += VolumeInfo.o
OBJS += VolumeLayout.o
OBJS += VolumePassword.o
OBJS += VolumePasswordCache.o
ifeq "$(CPU_ARCH)" "x86"
OBJS += ../Crypto/Aes_x86.o
OBJS += ../Crypto/Aes_hw_cpu.o
ifeq "$(PLATFORM)" "MacOSX"
OBJS += ../Crypto/Aescrypt.o
endif
else ifeq "$(CPU_ARCH)" "x64"
OBJS += ../Crypto/Aes_x64.o
OBJS += ../Crypto/Aes_hw_cpu.o
else
OBJS += ../Crypto/Aescrypt.o
endif
OBJS += ../Crypto/Aeskey.o
OBJS += ../Crypto/Aestab.o
OBJS += ../Crypto/Blowfish.o
OBJS += ../Crypto/Cast.o
OBJS += ../Crypto/Des.o
OBJS += ../Crypto/Rmd160.o
OBJS += ../Crypto/Serpent.o
OBJS += ../Crypto/Sha1.o
OBJS += ../Crypto/Sha2.o
OBJS += ../Crypto/Twofish.o
OBJS += ../Crypto/Whirlpool.o
OBJS += ../Common/Crc.o
OBJS += ../Common/Endian.o
OBJS += ../Common/GfMul.o
OBJS += ../Common/Pkcs5.o
OBJS += ../Common/SecurityToken.o
VolumeLibrary: Volume.a
include $(BUILD_INC)/Makefile.inc

View File

@@ -0,0 +1,32 @@
/*
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 "VolumeException.h"
#include "Platform/SerializerFactory.h"
namespace TrueCrypt
{
// Do not inline the constructors to ensure this module is not optimized away
VolumeException::VolumeException ()
{
}
VolumeException::VolumeException (const string &message) : Exception (message)
{
}
VolumeException::VolumeException (const string &message, const wstring &subject) : Exception (message, subject)
{
}
#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
#undef TC_EXCEPTION_NODECL
#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (VolumeException);
}

View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2008-2010 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.
*/
#ifndef TC_HEADER_Volume_VolumeExceptions
#define TC_HEADER_Volume_VolumeExceptions
#include "Platform/Platform.h"
namespace TrueCrypt
{
struct VolumeException : public Exception
{
protected:
VolumeException ();
VolumeException (const string &message);
VolumeException (const string &message, const wstring &subject);
};
#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,VolumeException)
#undef TC_EXCEPTION_SET
#define TC_EXCEPTION_SET \
TC_EXCEPTION (HigherVersionRequired); \
TC_EXCEPTION (KeyfilePathEmpty); \
TC_EXCEPTION (MissingVolumeData); \
TC_EXCEPTION (MountedVolumeInUse); \
TC_EXCEPTION (UnsupportedSectorSize); \
TC_EXCEPTION (VolumeEncryptionNotCompleted); \
TC_EXCEPTION (VolumeHostInUse); \
TC_EXCEPTION (VolumeProtected); \
TC_EXCEPTION (VolumeReadOnly);
TC_EXCEPTION_SET;
#undef TC_EXCEPTION
}
#endif // TC_HEADER_Volume_VolumeExceptions

340
src/Volume/VolumeHeader.cpp Normal file
View File

@@ -0,0 +1,340 @@
/*
Copyright (c) 2008-2010 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 "Crc32.h"
#include "EncryptionModeXTS.h"
#include "Pkcs5Kdf.h"
#include "Pkcs5Kdf.h"
#include "VolumeHeader.h"
#include "VolumeException.h"
#include "Common/Crypto.h"
namespace TrueCrypt
{
VolumeHeader::VolumeHeader (uint32 size)
{
Init();
HeaderSize = size;
EncryptedHeaderDataSize = size - EncryptedHeaderDataOffset;
}
VolumeHeader::~VolumeHeader ()
{
Init();
}
void VolumeHeader::Init ()
{
VolumeKeyAreaCrc32 = 0;
VolumeCreationTime = 0;
HeaderCreationTime = 0;
mVolumeType = VolumeType::Unknown;
HiddenVolumeDataSize = 0;
VolumeDataSize = 0;
EncryptedAreaStart = 0;
EncryptedAreaLength = 0;
Flags = 0;
SectorSize = 0;
}
void VolumeHeader::Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options)
{
if (options.DataKey.Size() != options.EA->GetKeySize() * 2 || options.Salt.Size() != GetSaltSize())
throw ParameterIncorrect (SRC_POS);
headerBuffer.Zero();
HeaderVersion = CurrentHeaderVersion;
RequiredMinProgramVersion = CurrentRequiredMinProgramVersion;
DataAreaKey.Zero();
DataAreaKey.CopyFrom (options.DataKey);
VolumeCreationTime = 0;
HiddenVolumeDataSize = (options.Type == VolumeType::Hidden ? options.VolumeDataSize : 0);
VolumeDataSize = options.VolumeDataSize;
EncryptedAreaStart = options.VolumeDataStart;
EncryptedAreaLength = options.VolumeDataSize;
SectorSize = options.SectorSize;
if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
|| SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
|| SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
{
throw ParameterIncorrect (SRC_POS);
}
EA = options.EA;
shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ());
EA->SetMode (mode);
EncryptNew (headerBuffer, options.Salt, options.HeaderKey, options.Kdf);
}
bool VolumeHeader::Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes)
{
if (password.Size() < 1)
throw PasswordEmpty (SRC_POS);
ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize));
SecureBuffer header (EncryptedHeaderDataSize);
SecureBuffer headerKey (GetLargestSerializedKeySize());
foreach (shared_ptr <Pkcs5Kdf> pkcs5, keyDerivationFunctions)
{
pkcs5->DeriveKey (headerKey, password, salt);
foreach (shared_ptr <EncryptionMode> mode, encryptionModes)
{
if (typeid (*mode) != typeid (EncryptionModeXTS))
mode->SetKey (headerKey.GetRange (0, mode->GetKeySize()));
foreach (shared_ptr <EncryptionAlgorithm> ea, encryptionAlgorithms)
{
if (!ea->IsModeSupported (mode))
continue;
if (typeid (*mode) == typeid (EncryptionModeXTS))
{
ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
mode = mode->GetNew();
mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
}
else
{
ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
}
ea->SetMode (mode);
header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize));
ea->Decrypt (header);
if (Deserialize (header, ea, mode))
{
EA = ea;
Pkcs5 = pkcs5;
return true;
}
}
}
}
return false;
}
bool VolumeHeader::Deserialize (const ConstBufferPtr &header, shared_ptr <EncryptionAlgorithm> &ea, shared_ptr <EncryptionMode> &mode)
{
if (header.Size() != EncryptedHeaderDataSize)
throw ParameterIncorrect (SRC_POS);
if (header[0] != 'T' ||
header[1] != 'R' ||
header[2] != 'U' ||
header[3] != 'E')
return false;
size_t offset = 4;
HeaderVersion = DeserializeEntry <uint16> (header, offset);
if (HeaderVersion < MinAllowedHeaderVersion)
return false;
if (HeaderVersion > CurrentHeaderVersion)
throw HigherVersionRequired (SRC_POS);
if (HeaderVersion >= 4
&& Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
!= DeserializeEntryAt <uint32> (header, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
{
return false;
}
RequiredMinProgramVersion = DeserializeEntry <uint16> (header, offset);
if (RequiredMinProgramVersion > Version::Number())
throw HigherVersionRequired (SRC_POS);
VolumeKeyAreaCrc32 = DeserializeEntry <uint32> (header, offset);
VolumeCreationTime = DeserializeEntry <uint64> (header, offset);
HeaderCreationTime = DeserializeEntry <uint64> (header, offset);
HiddenVolumeDataSize = DeserializeEntry <uint64> (header, offset);
mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal);
VolumeDataSize = DeserializeEntry <uint64> (header, offset);
EncryptedAreaStart = DeserializeEntry <uint64> (header, offset);
EncryptedAreaLength = DeserializeEntry <uint64> (header, offset);
Flags = DeserializeEntry <uint32> (header, offset);
SectorSize = DeserializeEntry <uint32> (header, offset);
if (HeaderVersion < 5)
SectorSize = TC_SECTOR_SIZE_LEGACY;
if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
|| SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
|| SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
{
throw ParameterIncorrect (SRC_POS);
}
#if !(defined (TC_WINDOWS) || defined (TC_LINUX))
if (SectorSize != TC_SECTOR_SIZE_LEGACY)
throw UnsupportedSectorSize (SRC_POS);
#endif
offset = DataAreaKeyOffset;
if (VolumeKeyAreaCrc32 != Crc32::ProcessBuffer (header.GetRange (offset, DataKeyAreaMaxSize)))
return false;
DataAreaKey.CopyFrom (header.GetRange (offset, DataKeyAreaMaxSize));
ea = ea->GetNew();
mode = mode->GetNew();
if (typeid (*mode) == typeid (EncryptionModeXTS))
{
ea->SetKey (header.GetRange (offset, ea->GetKeySize()));
mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize()));
}
else
{
mode->SetKey (header.GetRange (offset, mode->GetKeySize()));
ea->SetKey (header.GetRange (offset + LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
}
ea->SetMode (mode);
return true;
}
template <typename T>
T VolumeHeader::DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const
{
offset += sizeof (T);
if (offset > header.Size())
throw ParameterIncorrect (SRC_POS);
return Endian::Big (*reinterpret_cast<const T *> (header.Get() + offset - sizeof (T)));
}
template <typename T>
T VolumeHeader::DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const
{
if (offset > header.Size())
throw ParameterIncorrect (SRC_POS);
return Endian::Big (*reinterpret_cast<const T *> (header.Get() + offset));
}
void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf)
{
if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize)
throw ParameterIncorrect (SRC_POS);
shared_ptr <EncryptionMode> mode = EA->GetMode()->GetNew();
shared_ptr <EncryptionAlgorithm> ea = EA->GetNew();
if (typeid (*mode) == typeid (EncryptionModeXTS))
{
mode->SetKey (newHeaderKey.GetRange (EA->GetKeySize(), EA->GetKeySize()));
ea->SetKey (newHeaderKey.GetRange (0, ea->GetKeySize()));
}
else
{
mode->SetKey (newHeaderKey.GetRange (0, mode->GetKeySize()));
ea->SetKey (newHeaderKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
}
ea->SetMode (mode);
newHeaderBuffer.CopyFrom (newSalt);
BufferPtr headerData = newHeaderBuffer.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize);
Serialize (headerData);
ea->Encrypt (headerData);
if (newPkcs5Kdf)
Pkcs5 = newPkcs5Kdf;
}
size_t VolumeHeader::GetLargestSerializedKeySize ()
{
size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms());
// XTS mode requires the same key size as the encryption algorithm.
// Legacy modes may require larger key than XTS.
if (LegacyEncryptionModeKeyAreaSize + largestKey > largestKey * 2)
return LegacyEncryptionModeKeyAreaSize + largestKey;
return largestKey * 2;
}
void VolumeHeader::Serialize (const BufferPtr &header) const
{
if (header.Size() != EncryptedHeaderDataSize)
throw ParameterIncorrect (SRC_POS);
header.Zero();
header[0] = 'T';
header[1] = 'R';
header[2] = 'U';
header[3] = 'E';
size_t offset = 4;
header.GetRange (DataAreaKeyOffset, DataAreaKey.Size()).CopyFrom (DataAreaKey);
uint16 headerVersion = CurrentHeaderVersion;
SerializeEntry (headerVersion, header, offset);
SerializeEntry (RequiredMinProgramVersion, header, offset);
SerializeEntry (Crc32::ProcessBuffer (header.GetRange (DataAreaKeyOffset, DataKeyAreaMaxSize)), header, offset);
uint64 reserved64 = 0;
SerializeEntry (reserved64, header, offset);
SerializeEntry (reserved64, header, offset);
SerializeEntry (HiddenVolumeDataSize, header, offset);
SerializeEntry (VolumeDataSize, header, offset);
SerializeEntry (EncryptedAreaStart, header, offset);
SerializeEntry (EncryptedAreaLength, header, offset);
SerializeEntry (Flags, header, offset);
if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
|| SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
|| SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
{
throw ParameterIncorrect (SRC_POS);
}
SerializeEntry (SectorSize, header, offset);
offset = TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC;
SerializeEntry (Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)), header, offset);
}
template <typename T>
void VolumeHeader::SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const
{
offset += sizeof (T);
if (offset > header.Size())
throw ParameterIncorrect (SRC_POS);
*reinterpret_cast<T *> (header.Get() + offset - sizeof (T)) = Endian::Big (entry);
}
void VolumeHeader::SetSize (uint32 headerSize)
{
HeaderSize = headerSize;
EncryptedHeaderDataSize = HeaderSize - EncryptedHeaderDataOffset;
}
}

126
src/Volume/VolumeHeader.h Normal file
View File

@@ -0,0 +1,126 @@
/*
Copyright (c) 2008-2010 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.
*/
#ifndef TC_HEADER_Volume_VolumeHeader
#define TC_HEADER_Volume_VolumeHeader
#include "Common/Tcdefs.h"
#include "Common/Volumes.h"
#include "Platform/Platform.h"
#include "Volume/EncryptionAlgorithm.h"
#include "Volume/EncryptionMode.h"
#include "Volume/Keyfile.h"
#include "Volume/VolumePassword.h"
#include "Volume/Pkcs5Kdf.h"
#include "Version.h"
// For specifications of the volume header see Common/Volumes.c
namespace TrueCrypt
{
typedef uint64 VolumeTime;
struct VolumeType
{
enum Enum
{
Unknown,
Normal,
Hidden
};
};
struct VolumeHeaderCreationOptions
{
ConstBufferPtr DataKey;
shared_ptr <EncryptionAlgorithm> EA;
shared_ptr <Pkcs5Kdf> Kdf;
ConstBufferPtr HeaderKey;
ConstBufferPtr Salt;
uint32 SectorSize;
uint64 VolumeDataSize;
uint64 VolumeDataStart;
VolumeType::Enum Type;
};
class VolumeHeader
{
public:
VolumeHeader (uint32 HeaderSize);
virtual ~VolumeHeader ();
void Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options);
bool Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes);
void EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf);
uint64 GetEncryptedAreaStart () const { return EncryptedAreaStart; }
uint64 GetEncryptedAreaLength () const { return EncryptedAreaLength; }
shared_ptr <EncryptionAlgorithm> GetEncryptionAlgorithm () const { return EA; }
uint32 GetFlags () const { return Flags; }
VolumeTime GetHeaderCreationTime () const { return HeaderCreationTime; }
uint64 GetHiddenVolumeDataSize () const { return HiddenVolumeDataSize; }
static size_t GetLargestSerializedKeySize ();
shared_ptr <Pkcs5Kdf> GetPkcs5Kdf () const { return Pkcs5; }
uint16 GetRequiredMinProgramVersion () const { return RequiredMinProgramVersion; }
size_t GetSectorSize () const { return SectorSize; }
static uint32 GetSaltSize () { return SaltSize; }
uint64 GetVolumeDataSize () const { return VolumeDataSize; }
VolumeTime GetVolumeCreationTime () const { return VolumeCreationTime; }
void SetSize (uint32 headerSize);
protected:
bool Deserialize (const ConstBufferPtr &header, shared_ptr <EncryptionAlgorithm> &ea, shared_ptr <EncryptionMode> &mode);
template <typename T> T DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const;
template <typename T> T DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const;
void Init ();
void Serialize (const BufferPtr &header) const;
template <typename T> void SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const;
uint32 HeaderSize;
static const uint16 CurrentHeaderVersion = VOLUME_HEADER_VERSION;
static const uint16 CurrentRequiredMinProgramVersion = TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION;
static const uint16 MinAllowedHeaderVersion = 1;
static const int SaltOffset = 0;
static const uint32 SaltSize = 64;
static const int EncryptedHeaderDataOffset = SaltOffset + SaltSize;
uint32 EncryptedHeaderDataSize;
static const uint32 LegacyEncryptionModeKeyAreaSize = 32;
static const int DataKeyAreaMaxSize = 256;
static const uint32 DataAreaKeyOffset = DataKeyAreaMaxSize - EncryptedHeaderDataOffset;
shared_ptr <EncryptionAlgorithm> EA;
shared_ptr <Pkcs5Kdf> Pkcs5;
uint16 HeaderVersion;
uint16 RequiredMinProgramVersion;
uint32 VolumeKeyAreaCrc32;
VolumeTime VolumeCreationTime;
VolumeTime HeaderCreationTime;
VolumeType::Enum mVolumeType;
uint64 HiddenVolumeDataSize;
uint64 VolumeDataSize;
uint64 EncryptedAreaStart;
uint64 EncryptedAreaLength;
uint32 Flags;
uint32 SectorSize;
SecureBuffer DataAreaKey;
private:
VolumeHeader (const VolumeHeader &);
VolumeHeader &operator= (const VolumeHeader &);
};
}
#endif // TC_HEADER_Volume_VolumeHeader

118
src/Volume/VolumeInfo.cpp Normal file
View File

@@ -0,0 +1,118 @@
/*
Copyright (c) 2008-2009 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 "Common/Tcdefs.h"
#include "VolumeInfo.h"
#include "Platform/SerializerFactory.h"
namespace TrueCrypt
{
void VolumeInfo::Deserialize (shared_ptr <Stream> stream)
{
Serializer sr (stream);
sr.Deserialize ("ProgramVersion", ProgramVersion);
AuxMountPoint = sr.DeserializeWString ("AuxMountPoint");
sr.Deserialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize);
sr.Deserialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize);
sr.Deserialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize);
EncryptionAlgorithmName = sr.DeserializeWString ("EncryptionAlgorithmName");
EncryptionModeName = sr.DeserializeWString ("EncryptionModeName");
sr.Deserialize ("HeaderCreationTime", HeaderCreationTime);
sr.Deserialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered);
LoopDevice = sr.DeserializeWString ("LoopDevice");
if (ProgramVersion >= 0x600)
sr.Deserialize ("MinRequiredProgramVersion", MinRequiredProgramVersion);
MountPoint = sr.DeserializeWString ("MountPoint");
Path = sr.DeserializeWString ("Path");
sr.Deserialize ("Pkcs5IterationCount", Pkcs5IterationCount);
Pkcs5PrfName = sr.DeserializeWString ("Pkcs5PrfName");
Protection = static_cast <VolumeProtection::Enum> (sr.DeserializeInt32 ("Protection"));
sr.Deserialize ("SerialInstanceNumber", SerialInstanceNumber);
sr.Deserialize ("Size", Size);
sr.Deserialize ("SlotNumber", SlotNumber);
if (ProgramVersion >= 0x620)
sr.Deserialize ("SystemEncryption", SystemEncryption);
if (ProgramVersion >= 0x600)
sr.Deserialize ("TopWriteOffset", TopWriteOffset);
sr.Deserialize ("TotalDataRead", TotalDataRead);
sr.Deserialize ("TotalDataWritten", TotalDataWritten);
Type = static_cast <VolumeType::Enum> (sr.DeserializeInt32 ("Type"));
VirtualDevice = sr.DeserializeWString ("VirtualDevice");
sr.Deserialize ("VolumeCreationTime", VolumeCreationTime);
}
bool VolumeInfo::FirstVolumeMountedAfterSecond (shared_ptr <VolumeInfo> first, shared_ptr <VolumeInfo> second)
{
return first->SerialInstanceNumber > second->SerialInstanceNumber;
}
void VolumeInfo::Serialize (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
const uint32 version = VERSION_NUM;
sr.Serialize ("ProgramVersion", version);
sr.Serialize ("AuxMountPoint", wstring (AuxMountPoint));
sr.Serialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize);
sr.Serialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize);
sr.Serialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize);
sr.Serialize ("EncryptionAlgorithmName", EncryptionAlgorithmName);
sr.Serialize ("EncryptionModeName", EncryptionModeName);
sr.Serialize ("HeaderCreationTime", HeaderCreationTime);
sr.Serialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered);
sr.Serialize ("LoopDevice", wstring (LoopDevice));
sr.Serialize ("MinRequiredProgramVersion", MinRequiredProgramVersion);
sr.Serialize ("MountPoint", wstring (MountPoint));
sr.Serialize ("Path", wstring (Path));
sr.Serialize ("Pkcs5IterationCount", Pkcs5IterationCount);
sr.Serialize ("Pkcs5PrfName", Pkcs5PrfName);
sr.Serialize ("Protection", static_cast <uint32> (Protection));
sr.Serialize ("SerialInstanceNumber", SerialInstanceNumber);
sr.Serialize ("Size", Size);
sr.Serialize ("SlotNumber", SlotNumber);
sr.Serialize ("SystemEncryption", SystemEncryption);
sr.Serialize ("TopWriteOffset", TopWriteOffset);
sr.Serialize ("TotalDataRead", TotalDataRead);
sr.Serialize ("TotalDataWritten", TotalDataWritten);
sr.Serialize ("Type", static_cast <uint32> (Type));
sr.Serialize ("VirtualDevice", wstring (VirtualDevice));
sr.Serialize ("VolumeCreationTime", VolumeCreationTime);
}
void VolumeInfo::Set (const Volume &volume)
{
EncryptionAlgorithmBlockSize = static_cast <uint32> (volume.GetEncryptionAlgorithm()->GetMaxBlockSize());
EncryptionAlgorithmKeySize = static_cast <uint32> (volume.GetEncryptionAlgorithm()->GetKeySize());
EncryptionAlgorithmMinBlockSize = static_cast <uint32> (volume.GetEncryptionAlgorithm()->GetMinBlockSize());
EncryptionAlgorithmName = volume.GetEncryptionAlgorithm()->GetName();
EncryptionModeName = volume.GetEncryptionMode()->GetName();
HeaderCreationTime = volume.GetHeaderCreationTime();
VolumeCreationTime = volume.GetVolumeCreationTime();
HiddenVolumeProtectionTriggered = volume.IsHiddenVolumeProtectionTriggered();
MinRequiredProgramVersion = volume.GetHeader()->GetRequiredMinProgramVersion();
Path = volume.GetPath();
Pkcs5IterationCount = volume.GetPkcs5Kdf()->GetIterationCount();
Pkcs5PrfName = volume.GetPkcs5Kdf()->GetName();
Protection = volume.GetProtectionType();
Size = volume.GetSize();
SystemEncryption = volume.IsInSystemEncryptionScope();
Type = volume.GetType();
TopWriteOffset = volume.GetTopWriteOffset();
TotalDataRead = volume.GetTotalDataRead();
TotalDataWritten = volume.GetTotalDataWritten();
}
TC_SERIALIZER_FACTORY_ADD_CLASS (VolumeInfo);
}

66
src/Volume/VolumeInfo.h Normal file
View File

@@ -0,0 +1,66 @@
/*
Copyright (c) 2008-2009 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.
*/
#ifndef TC_HEADER_Volume_VolumeInfo
#define TC_HEADER_Volume_VolumeInfo
#include "Platform/Platform.h"
#include "Platform/Serializable.h"
#include "Volume/Volume.h"
#include "Volume/VolumeSlot.h"
namespace TrueCrypt
{
class VolumeInfo;
typedef list < shared_ptr <VolumeInfo> > VolumeInfoList;
class VolumeInfo : public Serializable
{
public:
VolumeInfo () { }
virtual ~VolumeInfo () { }
TC_SERIALIZABLE (VolumeInfo);
static bool FirstVolumeMountedAfterSecond (shared_ptr <VolumeInfo> first, shared_ptr <VolumeInfo> second);
void Set (const Volume &volume);
// Modifying this structure can introduce incompatibility with previous versions
DirectoryPath AuxMountPoint;
uint32 EncryptionAlgorithmBlockSize;
uint32 EncryptionAlgorithmKeySize;
uint32 EncryptionAlgorithmMinBlockSize;
wstring EncryptionAlgorithmName;
wstring EncryptionModeName;
VolumeTime HeaderCreationTime;
bool HiddenVolumeProtectionTriggered;
DevicePath LoopDevice;
uint32 MinRequiredProgramVersion;
DirectoryPath MountPoint;
VolumePath Path;
uint32 Pkcs5IterationCount;
wstring Pkcs5PrfName;
uint32 ProgramVersion;
VolumeProtection::Enum Protection;
uint64 SerialInstanceNumber;
uint64 Size;
VolumeSlotNumber SlotNumber;
bool SystemEncryption;
uint64 TopWriteOffset;
uint64 TotalDataRead;
uint64 TotalDataWritten;
VolumeType::Enum Type;
DevicePath VirtualDevice;
VolumeTime VolumeCreationTime;
private:
VolumeInfo (const VolumeInfo &);
VolumeInfo &operator= (const VolumeInfo &);
};
}
#endif // TC_HEADER_Volume_VolumeInfo

254
src/Volume/VolumeLayout.cpp Normal file
View File

@@ -0,0 +1,254 @@
/*
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 "Volume/EncryptionMode.h"
#include "Volume/EncryptionModeCBC.h"
#include "Volume/EncryptionModeLRW.h"
#include "Volume/EncryptionModeXTS.h"
#include "VolumeLayout.h"
#include "Boot/Windows/BootCommon.h"
namespace TrueCrypt
{
VolumeLayout::VolumeLayout ()
{
}
VolumeLayout::~VolumeLayout ()
{
}
VolumeLayoutList VolumeLayout::GetAvailableLayouts (VolumeType::Enum type)
{
VolumeLayoutList layouts;
layouts.push_back (shared_ptr <VolumeLayout> (new VolumeLayoutV2Normal ()));
layouts.push_back (shared_ptr <VolumeLayout> (new VolumeLayoutV1Normal ()));
layouts.push_back (shared_ptr <VolumeLayout> (new VolumeLayoutV2Hidden ()));
layouts.push_back (shared_ptr <VolumeLayout> (new VolumeLayoutV1Hidden ()));
layouts.push_back (shared_ptr <VolumeLayout> (new VolumeLayoutSystemEncryption ()));
if (type != VolumeType::Unknown)
{
VolumeLayoutList l;
foreach (shared_ptr <VolumeLayout> vl, layouts)
{
if (vl->GetType() == type)
l.push_back (vl);
}
layouts = l;
}
return layouts;
}
shared_ptr <VolumeHeader> VolumeLayout::GetHeader ()
{
if (Header.get() == nullptr)
Header.reset (new VolumeHeader (GetHeaderSize()));
return Header;
}
VolumeLayoutV1Normal::VolumeLayoutV1Normal ()
{
Type = VolumeType::Normal;
HeaderOffset = TC_VOLUME_HEADER_OFFSET;
HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY;
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Blowfish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Cast5 ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TripleDES ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
uint64 VolumeLayoutV1Normal::GetDataOffset (uint64 volumeHostSize) const
{
return HeaderSize;
}
uint64 VolumeLayoutV1Normal::GetDataSize (uint64 volumeHostSize) const
{
return volumeHostSize - GetHeaderSize();
}
VolumeLayoutV1Hidden::VolumeLayoutV1Hidden ()
{
Type = VolumeType::Hidden;
HeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY;
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESBlowfishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Blowfish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Cast5 ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TripleDES ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeLRW ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeCBC ()));
}
uint64 VolumeLayoutV1Hidden::GetDataOffset (uint64 volumeHostSize) const
{
return volumeHostSize - GetDataSize (volumeHostSize) + HeaderOffset;
}
uint64 VolumeLayoutV1Hidden::GetDataSize (uint64 volumeHostSize) const
{
return Header->GetHiddenVolumeDataSize ();
}
VolumeLayoutV2Normal::VolumeLayoutV2Normal ()
{
Type = VolumeType::Normal;
HeaderOffset = TC_VOLUME_HEADER_OFFSET;
HeaderSize = TC_VOLUME_HEADER_SIZE;
BackupHeaderOffset = -TC_VOLUME_HEADER_GROUP_SIZE;
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
uint64 VolumeLayoutV2Normal::GetDataOffset (uint64 volumeHostSize) const
{
return Header->GetEncryptedAreaStart();
}
uint64 VolumeLayoutV2Normal::GetDataSize (uint64 volumeHostSize) const
{
return Header->GetVolumeDataSize();
}
uint64 VolumeLayoutV2Normal::GetMaxDataSize (uint64 volumeSize) const
{
if (volumeSize < TC_TOTAL_VOLUME_HEADERS_SIZE)
return 0;
return volumeSize - TC_TOTAL_VOLUME_HEADERS_SIZE;
}
VolumeLayoutV2Hidden::VolumeLayoutV2Hidden ()
{
Type = VolumeType::Hidden;
HeaderOffset = TC_HIDDEN_VOLUME_HEADER_OFFSET;
HeaderSize = TC_VOLUME_HEADER_SIZE;
BackupHeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET;
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
uint64 VolumeLayoutV2Hidden::GetDataOffset (uint64 volumeHostSize) const
{
return Header->GetEncryptedAreaStart();
}
uint64 VolumeLayoutV2Hidden::GetDataSize (uint64 volumeHostSize) const
{
return Header->GetVolumeDataSize();
}
uint64 VolumeLayoutV2Hidden::GetMaxDataSize (uint64 volumeSize) const
{
// Reserve free space at the end of the host filesystem
uint64 reservedSize;
if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD)
reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE;
else
reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size
if (volumeSize < reservedSize)
return 0;
return volumeSize - reservedSize;
}
VolumeLayoutSystemEncryption::VolumeLayoutSystemEncryption ()
{
Type = VolumeType::Normal;
HeaderOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
HeaderSize = TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE;
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentTwofishAES ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new TwofishSerpent ()));
SupportedEncryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
uint64 VolumeLayoutSystemEncryption::GetDataOffset (uint64 volumeHostSize) const
{
return 0;
}
uint64 VolumeLayoutSystemEncryption::GetDataSize (uint64 volumeHostSize) const
{
return volumeHostSize;
}
Pkcs5KdfList VolumeLayoutSystemEncryption::GetSupportedKeyDerivationFunctions () const
{
Pkcs5KdfList l;
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacRipemd160_1000 ()));
return l;
}
}

153
src/Volume/VolumeLayout.h Normal file
View File

@@ -0,0 +1,153 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_VolumeLayout
#define TC_HEADER_Volume_VolumeLayout
#include "Platform/Platform.h"
#include "Volume/EncryptionAlgorithm.h"
#include "Volume/EncryptionMode.h"
#include "Volume/Pkcs5Kdf.h"
#include "VolumeHeader.h"
namespace TrueCrypt
{
class VolumeLayout;
typedef list < shared_ptr <VolumeLayout> > VolumeLayoutList;
class VolumeLayout
{
public:
virtual ~VolumeLayout ();
static VolumeLayoutList GetAvailableLayouts (VolumeType::Enum type = VolumeType::Unknown);
virtual int GetBackupHeaderOffset () const { return BackupHeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end
virtual uint64 GetDataOffset (uint64 volumeHostSize) const = 0;
virtual uint64 GetDataSize (uint64 volumeHostSize) const = 0;
virtual shared_ptr <VolumeHeader> GetHeader ();
virtual int GetHeaderOffset () const { return HeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end
virtual uint32 GetHeaderSize () const { return HeaderSize; }
virtual uint64 GetMaxDataSize (uint64 volumeSize) const = 0;
virtual EncryptionAlgorithmList GetSupportedEncryptionAlgorithms () const { return SupportedEncryptionAlgorithms; }
virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const { return Pkcs5Kdf::GetAvailableAlgorithms(); }
virtual EncryptionModeList GetSupportedEncryptionModes () const { return SupportedEncryptionModes; }
virtual VolumeType::Enum GetType () const { return Type; }
virtual bool HasBackupHeader () const = 0;
virtual bool HasDriveHeader () const { return false; }
virtual void SetHeader (shared_ptr <VolumeHeader> header) { Header = header; }
protected:
VolumeLayout ();
EncryptionAlgorithmList SupportedEncryptionAlgorithms;
EncryptionModeList SupportedEncryptionModes;
int BackupHeaderOffset;
int HeaderOffset;
uint32 HeaderSize;
VolumeType::Enum Type;
shared_ptr <VolumeHeader> Header;
private:
VolumeLayout (const VolumeLayout &);
VolumeLayout &operator= (const VolumeLayout &);
};
class VolumeLayoutV1Normal : public VolumeLayout
{
public:
VolumeLayoutV1Normal ();
virtual ~VolumeLayoutV1Normal () { }
virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); }
virtual uint64 GetDataOffset (uint64 volumeHostSize) const;
virtual uint64 GetDataSize (uint64 volumeHostSize) const;
virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); }
virtual bool HasBackupHeader () const { return false; }
private:
VolumeLayoutV1Normal (const VolumeLayoutV1Normal &);
VolumeLayoutV1Normal &operator= (const VolumeLayoutV1Normal &);
};
class VolumeLayoutV1Hidden : public VolumeLayout
{
public:
VolumeLayoutV1Hidden ();
virtual ~VolumeLayoutV1Hidden () { }
virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); }
virtual uint64 GetDataOffset (uint64 volumeHostSize) const;
virtual uint64 GetDataSize (uint64 volumeHostSize) const;
virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); }
virtual bool HasBackupHeader () const { return false; }
private:
VolumeLayoutV1Hidden (const VolumeLayoutV1Hidden &);
VolumeLayoutV1Hidden &operator= (const VolumeLayoutV1Hidden &);
};
class VolumeLayoutV2Normal : public VolumeLayout
{
public:
VolumeLayoutV2Normal ();
virtual ~VolumeLayoutV2Normal () { }
virtual uint64 GetDataOffset (uint64 volumeHostSize) const;
virtual uint64 GetDataSize (uint64 volumeHostSize) const;
virtual uint64 GetMaxDataSize (uint64 volumeSize) const;
virtual bool HasBackupHeader () const { return true; }
private:
VolumeLayoutV2Normal (const VolumeLayoutV2Normal &);
VolumeLayoutV2Normal &operator= (const VolumeLayoutV2Normal &);
};
class VolumeLayoutV2Hidden : public VolumeLayout
{
public:
VolumeLayoutV2Hidden ();
virtual ~VolumeLayoutV2Hidden () { }
virtual uint64 GetDataOffset (uint64 volumeHostSize) const;
virtual uint64 GetDataSize (uint64 volumeHostSize) const;
virtual uint64 GetMaxDataSize (uint64 volumeSize) const;
virtual bool HasBackupHeader () const { return true; }
private:
VolumeLayoutV2Hidden (const VolumeLayoutV2Hidden &);
VolumeLayoutV2Hidden &operator= (const VolumeLayoutV2Hidden &);
};
class VolumeLayoutSystemEncryption : public VolumeLayout
{
public:
VolumeLayoutSystemEncryption ();
virtual ~VolumeLayoutSystemEncryption () { }
virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); }
virtual uint64 GetDataOffset (uint64 volumeHostSize) const;
virtual uint64 GetDataSize (uint64 volumeHostSize) const;
virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); }
virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const;
virtual bool HasBackupHeader () const { return false; }
virtual bool HasDriveHeader () const { return true; }
private:
VolumeLayoutSystemEncryption (const VolumeLayoutSystemEncryption &);
VolumeLayoutSystemEncryption &operator= (const VolumeLayoutSystemEncryption &);
};
}
#endif // TC_HEADER_Volume_VolumeLayout

View File

@@ -0,0 +1,167 @@
/*
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 "VolumePassword.h"
#include "Platform/SerializerFactory.h"
#include "Platform/StringConverter.h"
namespace TrueCrypt
{
VolumePassword::VolumePassword () : PasswordSize (0), Unportable (false)
{
AllocateBuffer ();
}
VolumePassword::VolumePassword (const char *password, size_t size)
{
Set ((const byte *) password, size);
}
VolumePassword::VolumePassword (const byte *password, size_t size)
{
Set (password, size);
}
VolumePassword::VolumePassword (const wchar_t *password, size_t charCount)
{
Set (password, charCount);
}
VolumePassword::VolumePassword (const wstring &password)
{
Set (password.c_str(), password.size());
}
VolumePassword::~VolumePassword ()
{
}
void VolumePassword::AllocateBuffer ()
{
if (!PasswordBuffer.IsAllocated ())
PasswordBuffer.Allocate (MaxSize);
}
void VolumePassword::CheckPortability () const
{
if (Unportable || !IsPortable())
throw UnportablePassword (SRC_POS);
}
void VolumePassword::Deserialize (shared_ptr <Stream> stream)
{
Serializer sr (stream);
uint64 passwordSize;
sr.Deserialize ("PasswordSize", passwordSize);
PasswordSize = static_cast <size_t> (passwordSize);
sr.Deserialize ("PasswordBuffer", BufferPtr (PasswordBuffer));
Buffer wipeBuffer (128 * 1024);
sr.Deserialize ("WipeData", wipeBuffer);
}
bool VolumePassword::IsPortable () const
{
for (size_t i = 0; i < PasswordSize; i++)
{
if (PasswordBuffer[i] >= 0x7f || PasswordBuffer[i] < 0x20)
return false;
}
return true;
}
void VolumePassword::Serialize (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("PasswordSize", static_cast <uint64> (PasswordSize));
sr.Serialize ("PasswordBuffer", ConstBufferPtr (PasswordBuffer));
// Wipe password from an eventual pipe buffer
Buffer wipeBuffer (128 * 1024);
wipeBuffer.Zero();
sr.Serialize ("WipeData", ConstBufferPtr (wipeBuffer));
}
void VolumePassword::Set (const byte *password, size_t size)
{
AllocateBuffer ();
if (size > MaxSize)
throw PasswordTooLong (SRC_POS);
PasswordBuffer.CopyFrom (ConstBufferPtr (password, size));
PasswordSize = size;
Unportable = !IsPortable();
}
void VolumePassword::Set (const wchar_t *password, size_t charCount)
{
if (charCount > MaxSize)
throw PasswordTooLong (SRC_POS);
union Conv
{
byte b[sizeof (wchar_t)];
wchar_t c;
};
Conv conv;
conv.c = L'A';
int lsbPos = -1;
for (size_t i = 0; i < sizeof (conv.b); ++i)
{
if (conv.b[i] == L'A')
{
lsbPos = i;
break;
}
}
if (lsbPos == -1)
throw ParameterIncorrect (SRC_POS);
bool unportable = false;
byte passwordBuf[MaxSize];
for (size_t i = 0; i < charCount; ++i)
{
conv.c = password[i];
passwordBuf[i] = conv.b[lsbPos];
for (int j = 0; j < (int) sizeof (wchar_t); ++j)
{
if (j != lsbPos && conv.b[j] != 0)
unportable = true;
}
}
Set (passwordBuf, charCount);
if (unportable)
Unportable = true;
}
void VolumePassword::Set (const ConstBufferPtr &password)
{
Set (password, password.Size());
}
void VolumePassword::Set (const VolumePassword &password)
{
Set (password.DataPtr(), password.Size());
}
TC_SERIALIZER_FACTORY_ADD_CLASS (VolumePassword);
#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
#undef TC_EXCEPTION_NODECL
#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (PasswordException);
}

View File

@@ -0,0 +1,92 @@
/*
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.
*/
#ifndef TC_HEADER_Encryption_Password
#define TC_HEADER_Encryption_Password
#include "Platform/Platform.h"
#include "Platform/Serializable.h"
namespace TrueCrypt
{
class VolumePassword : public Serializable
{
public:
VolumePassword ();
VolumePassword (const byte *password, size_t size);
VolumePassword (const char *password, size_t size);
VolumePassword (const wchar_t *password, size_t charCount);
VolumePassword (const wstring &password);
VolumePassword (const VolumePassword &password) { Set (password); }
virtual ~VolumePassword ();
bool operator== (const VolumePassword &other) const { return ConstBufferPtr (DataPtr(), Size()).IsDataEqual (ConstBufferPtr (other.DataPtr(), other.Size())); }
bool operator!= (const VolumePassword &other) const { return !(*this == other); }
VolumePassword &operator= (const VolumePassword &password) { Set (password); return *this; }
operator BufferPtr () const { return BufferPtr (PasswordBuffer); }
void CheckPortability () const;
byte *DataPtr () const { return PasswordBuffer; }
bool IsEmpty () const { return PasswordSize == 0; }
size_t Size () const { return PasswordSize; }
void Set (const byte *password, size_t size);
void Set (const wchar_t *password, size_t charCount);
void Set (const ConstBufferPtr &password);
void Set (const VolumePassword &password);
TC_SERIALIZABLE (VolumePassword);
static const size_t MaxSize = 64;
static const size_t WarningSizeThreshold = 12;
protected:
void AllocateBuffer ();
bool IsPortable () const;
SecureBuffer PasswordBuffer;
size_t PasswordSize;
bool Unportable;
};
struct PasswordException : public Exception
{
protected:
PasswordException () { }
PasswordException (const string &message) : Exception (message) { }
PasswordException (const string &message, const wstring &subject) : Exception (message, subject) { }
};
TC_EXCEPTION_DECL (PasswordIncorrect, PasswordException);
TC_EXCEPTION_DECL (PasswordKeyfilesIncorrect, PasswordIncorrect);
TC_EXCEPTION_DECL (PasswordOrKeyboardLayoutIncorrect, PasswordException);
TC_EXCEPTION_DECL (PasswordOrMountOptionsIncorrect, PasswordException);
TC_EXCEPTION_DECL (ProtectionPasswordIncorrect, PasswordIncorrect);
TC_EXCEPTION_DECL (ProtectionPasswordKeyfilesIncorrect, PasswordIncorrect);
#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,PasswordException)
#undef TC_EXCEPTION_SET
#define TC_EXCEPTION_SET \
TC_EXCEPTION_NODECL (PasswordIncorrect); \
TC_EXCEPTION_NODECL (PasswordKeyfilesIncorrect); \
TC_EXCEPTION_NODECL (PasswordOrKeyboardLayoutIncorrect); \
TC_EXCEPTION_NODECL (PasswordOrMountOptionsIncorrect); \
TC_EXCEPTION_NODECL (ProtectionPasswordIncorrect); \
TC_EXCEPTION_NODECL (ProtectionPasswordKeyfilesIncorrect); \
TC_EXCEPTION (PasswordEmpty); \
TC_EXCEPTION (PasswordTooLong); \
TC_EXCEPTION (UnportablePassword);
TC_EXCEPTION_SET;
#undef TC_EXCEPTION
}
#endif // TC_HEADER_Encryption_Password

View File

@@ -0,0 +1,43 @@
/*
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 "VolumePasswordCache.h"
namespace TrueCrypt
{
CachedPasswordList VolumePasswordCache::GetPasswords ()
{
CachedPasswordList passwords;
foreach_ref (const VolumePassword &password, CachedPasswords)
passwords.push_back (make_shared <VolumePassword> (VolumePassword (password)));
return passwords;
}
void VolumePasswordCache::Store (const VolumePassword &newPassword)
{
CachedPasswordList::iterator iter = CachedPasswords.begin();
foreach_ref (const VolumePassword &password, CachedPasswords)
{
if (newPassword == password)
{
CachedPasswords.erase (iter);
break;
}
iter++;
}
CachedPasswords.push_front (make_shared <VolumePassword> (VolumePassword (newPassword)));
if (CachedPasswords.size() > Capacity)
CachedPasswords.pop_back();
}
CachedPasswordList VolumePasswordCache::CachedPasswords;
}

View File

@@ -0,0 +1,36 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_VolumePasswordCache
#define TC_HEADER_Volume_VolumePasswordCache
#include "Platform/Platform.h"
#include "VolumePassword.h"
namespace TrueCrypt
{
typedef list < shared_ptr < VolumePassword > > CachedPasswordList;
class VolumePasswordCache
{
public:
static CachedPasswordList GetPasswords ();
static bool IsEmpty () { return CachedPasswords.empty(); }
static void Store (const VolumePassword &newPassword);
static void Clear () { CachedPasswords.clear(); }
static const size_t Capacity = 4;
protected:
static CachedPasswordList CachedPasswords;
private:
VolumePasswordCache ();
};
}
#endif // TC_HEADER_Volume_VolumePasswordCache

19
src/Volume/VolumeSlot.h Normal file
View File

@@ -0,0 +1,19 @@
/*
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.
*/
#ifndef TC_HEADER_Volume_VolumeSlot
#define TC_HEADER_Volume_VolumeSlot
#include "Platform/Platform.h"
namespace TrueCrypt
{
typedef uint32 VolumeSlotNumber;
}
#endif // TC_HEADER_Volume_VolumeSlot