VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Volume
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2014-05-31 18:44:53 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2014-11-08 23:18:59 +0100
commit7ffce028d04a6b13ef762e2b89c34b688e8ca59d (patch)
treeeefedb6e94de5b26fa963675969490c641c29077 /src/Volume
parent97011f179cfd3dcd12446ef4ccb6964c8e52c3db (diff)
downloadVeraCrypt-7ffce028d04a6b13ef762e2b89c34b688e8ca59d.tar.gz
VeraCrypt-7ffce028d04a6b13ef762e2b89c34b688e8ca59d.zip
Add TrueCrypt 7.1a MacOSX/Linux specific source files.
Diffstat (limited to 'src/Volume')
-rw-r--r--src/Volume/Cipher.cpp314
-rw-r--r--src/Volume/Cipher.h129
-rw-r--r--src/Volume/Crc32.h44
-rw-r--r--src/Volume/EncryptionAlgorithm.cpp345
-rw-r--r--src/Volume/EncryptionAlgorithm.h93
-rw-r--r--src/Volume/EncryptionMode.cpp63
-rw-r--r--src/Volume/EncryptionMode.h62
-rw-r--r--src/Volume/EncryptionModeCBC.cpp335
-rw-r--r--src/Volume/EncryptionModeCBC.h47
-rw-r--r--src/Volume/EncryptionModeLRW.cpp195
-rw-r--r--src/Volume/EncryptionModeLRW.h50
-rw-r--r--src/Volume/EncryptionModeXTS.cpp374
-rw-r--r--src/Volume/EncryptionModeXTS.h50
-rw-r--r--src/Volume/EncryptionTest.cpp890
-rw-r--r--src/Volume/EncryptionTest.h50
-rw-r--r--src/Volume/EncryptionThreadPool.cpp325
-rw-r--r--src/Volume/EncryptionThreadPool.h87
-rw-r--r--src/Volume/Hash.cpp138
-rw-r--r--src/Volume/Hash.h135
-rw-r--r--src/Volume/Keyfile.cpp181
-rw-r--r--src/Volume/Keyfile.h49
-rw-r--r--src/Volume/Pkcs5Kdf.cpp96
-rw-r--r--src/Volume/Pkcs5Kdf.h127
-rw-r--r--src/Volume/Version.h25
-rw-r--r--src/Volume/Volume.cpp388
-rw-r--r--src/Volume/Volume.h126
-rw-r--r--src/Volume/Volume.make62
-rw-r--r--src/Volume/VolumeException.cpp32
-rw-r--r--src/Volume/VolumeException.h43
-rw-r--r--src/Volume/VolumeHeader.cpp340
-rw-r--r--src/Volume/VolumeHeader.h126
-rw-r--r--src/Volume/VolumeInfo.cpp118
-rw-r--r--src/Volume/VolumeInfo.h66
-rw-r--r--src/Volume/VolumeLayout.cpp254
-rw-r--r--src/Volume/VolumeLayout.h153
-rw-r--r--src/Volume/VolumePassword.cpp167
-rw-r--r--src/Volume/VolumePassword.h92
-rw-r--r--src/Volume/VolumePasswordCache.cpp43
-rw-r--r--src/Volume/VolumePasswordCache.h36
-rw-r--r--src/Volume/VolumeSlot.h19
40 files changed, 6269 insertions, 0 deletions
diff --git a/src/Volume/Cipher.cpp b/src/Volume/Cipher.cpp
new file mode 100644
index 00000000..fa37e298
--- /dev/null
+++ b/src/Volume/Cipher.cpp
@@ -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;
+}
diff --git a/src/Volume/Cipher.h b/src/Volume/Cipher.h
new file mode 100644
index 00000000..25fc82c9
--- /dev/null
+++ b/src/Volume/Cipher.h
@@ -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
diff --git a/src/Volume/Crc32.h b/src/Volume/Crc32.h
new file mode 100644
index 00000000..d4392275
--- /dev/null
+++ b/src/Volume/Crc32.h
@@ -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
diff --git a/src/Volume/EncryptionAlgorithm.cpp b/src/Volume/EncryptionAlgorithm.cpp
new file mode 100644
index 00000000..5ca27bab
--- /dev/null
+++ b/src/Volume/EncryptionAlgorithm.cpp
@@ -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 ()));
+ }
+}
diff --git a/src/Volume/EncryptionAlgorithm.h b/src/Volume/EncryptionAlgorithm.h
new file mode 100644
index 00000000..8118de6b
--- /dev/null
+++ b/src/Volume/EncryptionAlgorithm.h
@@ -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
diff --git a/src/Volume/EncryptionMode.cpp b/src/Volume/EncryptionMode.cpp
new file mode 100644
index 00000000..eb68186c
--- /dev/null
+++ b/src/Volume/EncryptionMode.cpp
@@ -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);
+ }
+}
diff --git a/src/Volume/EncryptionMode.h b/src/Volume/EncryptionMode.h
new file mode 100644
index 00000000..e74fca55
--- /dev/null
+++ b/src/Volume/EncryptionMode.h
@@ -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
diff --git a/src/Volume/EncryptionModeCBC.cpp b/src/Volume/EncryptionModeCBC.cpp
new file mode 100644
index 00000000..f299b888
--- /dev/null
+++ b/src/Volume/EncryptionModeCBC.cpp
@@ -0,0 +1,335 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Platform/Memory.h"
+#include "Common/Crc.h"
+#include "Common/Endian.h"
+#include "EncryptionModeCBC.h"
+
+namespace TrueCrypt
+{
+ void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, length));
+
+ if (IsOuterCBC (Ciphers))
+ {
+ DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
+ }
+ else
+ {
+ for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
+ iCipherList != Ciphers.rend();
+ ++iCipherList)
+ {
+ CipherList cl;
+ cl.push_back (*iCipherList);
+
+ DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
+ }
+ }
+ }
+
+ void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
+ {
+ size_t blockSize = ciphers.front()->GetBlockSize();
+ if (blockSize != 8 && blockSize != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ uint32 *data32 = (uint32 *) data;
+ uint32 bufIV[4];
+ uint32 ct[4];
+ uint64 i;
+
+ bufIV[0] = iv[0];
+ bufIV[1] = iv[1];
+ if (blockSize == 16)
+ {
+ bufIV[2] = iv[2];
+ bufIV[3] = iv[3];
+ }
+
+ for (i = 0; i < length / blockSize; i++)
+ {
+ // Dewhitening
+ data32[0] ^= whitening[0];
+ data32[1] ^= whitening[1];
+ if (blockSize == 16)
+ {
+ data32[2] ^= whitening[0];
+ data32[3] ^= whitening[1];
+ }
+
+ // CBC
+ ct[0] = data32[0];
+ ct[1] = data32[1];
+ if (blockSize == 16)
+ {
+ ct[2] = data32[2];
+ ct[3] = data32[3];
+ }
+
+ for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin();
+ iCipherList != ciphers.rend();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+
+ if (c.GetBlockSize () != blockSize)
+ throw ParameterIncorrect (SRC_POS);
+
+ c.DecryptBlock ((byte *) data32);
+ }
+
+ // CBC
+ data32[0] ^= bufIV[0];
+ data32[1] ^= bufIV[1];
+ bufIV[0] = ct[0];
+ bufIV[1] = ct[1];
+ if (blockSize == 16)
+ {
+ data32[2] ^= bufIV[2];
+ data32[3] ^= bufIV[3];
+ bufIV[2] = ct[2];
+ bufIV[3] = ct[3];
+ }
+
+ data32 += blockSize / sizeof(*data32);
+ }
+
+ Memory::Erase (bufIV, sizeof (bufIV));
+ Memory::Erase (ct, sizeof (ct));
+ }
+
+ void EncryptionModeCBC::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, sectorCount, sectorSize));
+
+ uint32 sectorIV[4];
+ uint32 sectorWhitening[2];
+
+ while (sectorCount--)
+ {
+ if (IsOuterCBC (Ciphers))
+ {
+ InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
+ DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
+ }
+ else
+ {
+ for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
+ iCipherList != Ciphers.rend();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+ CipherList cl;
+ cl.push_back (*iCipherList);
+
+ InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
+ DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
+ }
+ }
+
+ data += sectorSize;
+ sectorIndex++;
+ }
+
+ Memory::Erase (sectorIV, sizeof (sectorIV));
+ Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
+ }
+
+ void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, length));
+
+ if (IsOuterCBC (Ciphers))
+ {
+ EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
+ }
+ else
+ {
+ for (CipherList::const_iterator iCipherList = Ciphers.begin();
+ iCipherList != Ciphers.end();
+ ++iCipherList)
+ {
+ CipherList cl;
+ cl.push_back (*iCipherList);
+
+ EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
+ }
+ }
+ }
+
+ void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
+ {
+ size_t blockSize = ciphers.front()->GetBlockSize();
+ if (blockSize != 8 && blockSize != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ uint32 *data32 = (uint32 *) data;
+ uint32 bufIV[4];
+ uint64 i;
+
+ bufIV[0] = iv[0];
+ bufIV[1] = iv[1];
+ if (blockSize == 16)
+ {
+ bufIV[2] = iv[2];
+ bufIV[3] = iv[3];
+ }
+
+ for (i = 0; i < length / blockSize; i++)
+ {
+ data32[0] ^= bufIV[0];
+ data32[1] ^= bufIV[1];
+ if (blockSize == 16)
+ {
+ data32[2] ^= bufIV[2];
+ data32[3] ^= bufIV[3];
+ }
+
+ for (CipherList::const_iterator iCipherList = ciphers.begin();
+ iCipherList != ciphers.end();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+
+ if (c.GetBlockSize () != blockSize)
+ throw ParameterIncorrect (SRC_POS);
+
+ c.EncryptBlock ((byte *) data32);
+ }
+
+ bufIV[0] = data32[0];
+ bufIV[1] = data32[1];
+ if (blockSize == 16)
+ {
+ bufIV[2] = data32[2];
+ bufIV[3] = data32[3];
+ }
+
+ data32[0] ^= whitening[0];
+ data32[1] ^= whitening[1];
+ if (blockSize == 16)
+ {
+ data32[2] ^= whitening[0];
+ data32[3] ^= whitening[1];
+ }
+
+ data32 += blockSize / sizeof(*data32);
+ }
+
+ Memory::Erase (bufIV, sizeof (bufIV));
+ }
+
+ void EncryptionModeCBC::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, sectorCount, sectorSize));
+
+ uint32 sectorIV[4];
+ uint32 sectorWhitening[2];
+
+ while (sectorCount--)
+ {
+ if (IsOuterCBC (Ciphers))
+ {
+ InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
+ EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
+ }
+ else
+ {
+ for (CipherList::const_iterator iCipherList = Ciphers.begin();
+ iCipherList != Ciphers.end();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+ CipherList cl;
+ cl.push_back (*iCipherList);
+
+ InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
+ EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
+ }
+ }
+
+ data += sectorSize;
+ sectorIndex++;
+ }
+
+ Memory::Erase (sectorIV, sizeof (sectorIV));
+ Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
+ }
+
+ void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const
+ {
+ if (blockSize != 8 && blockSize != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ uint64 iv64[4];
+ uint32 *iv32 = (uint32 *) iv64;
+
+ iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex);
+ iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex);
+ iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex);
+ if (blockSize == 16)
+ {
+ iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex);
+ }
+
+ iv[0] = iv32[0];
+ iv[1] = iv32[1];
+
+ if (blockSize == 8)
+ {
+ whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) );
+ whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) );
+ }
+ else
+ {
+ iv[2] = iv32[2];
+ iv[3] = iv32[3];
+
+ whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) );
+ whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) );
+ }
+ }
+
+ bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const
+ {
+ if (ciphers.size() < 2)
+ return false;
+
+ size_t blockSize = ciphers.front()->GetBlockSize();
+
+ for (CipherList::const_iterator iCipherList = ciphers.begin();
+ iCipherList != ciphers.end();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+ if (c.GetBlockSize() != blockSize)
+ return false;
+ }
+
+ return true;
+ }
+
+ void EncryptionModeCBC::SetKey (const ConstBufferPtr &key)
+ {
+ if (key.Size() != GetKeySize ())
+ throw ParameterIncorrect (SRC_POS);
+
+ if (!KeySet)
+ IV.Allocate (GetKeySize ());
+
+ IV.CopyFrom (key);
+ KeySet = true;
+ }
+}
diff --git a/src/Volume/EncryptionModeCBC.h b/src/Volume/EncryptionModeCBC.h
new file mode 100644
index 00000000..3e1094aa
--- /dev/null
+++ b/src/Volume/EncryptionModeCBC.h
@@ -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
diff --git a/src/Volume/EncryptionModeLRW.cpp b/src/Volume/EncryptionModeLRW.cpp
new file mode 100644
index 00000000..38731d5d
--- /dev/null
+++ b/src/Volume/EncryptionModeLRW.cpp
@@ -0,0 +1,195 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "EncryptionModeLRW.h"
+#include "Common/GfMul.h"
+
+namespace TrueCrypt
+{
+ void EncryptionModeLRW::Decrypt (byte *data, uint64 length) const
+ {
+ if_debug (ValidateState ());
+ DecryptBuffer (data, length, 1);
+ }
+
+ void EncryptionModeLRW::DecryptBuffer (byte *data, uint64 length, uint64 blockIndex) const
+ {
+ size_t blockSize = Ciphers.front()->GetBlockSize();
+ if (blockSize != 8 && blockSize != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ byte i[8];
+ *(uint64 *)i = Endian::Big (blockIndex);
+
+ byte t[Cipher::MaxBlockSize];
+
+ for (unsigned int b = 0; b < length / blockSize; b++)
+ {
+ if (blockSize == 8)
+ {
+ Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr()));
+ Xor64 ((uint64 *)data, (uint64 *)t);
+ }
+ else
+ {
+ Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr()));
+ Xor128 ((uint64 *)data, (uint64 *)t);
+ }
+
+ for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
+ iCipherList != Ciphers.rend();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+
+ if (c.GetBlockSize () != blockSize)
+ throw ParameterIncorrect (SRC_POS);
+
+ c.DecryptBlock (data);
+ }
+
+ if (blockSize == 8)
+ Xor64 ((uint64 *)data, (uint64 *)t);
+ else
+ Xor128 ((uint64 *)data, (uint64 *)t);
+
+ data += blockSize;
+ IncrementBlockIndex (i);
+ }
+
+ Memory::Erase (t, sizeof (t));
+ }
+
+ void EncryptionModeLRW::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, sectorCount, sectorSize));
+
+ DecryptBuffer (data,
+ sectorCount * sectorSize,
+ SectorToBlockIndex (sectorIndex));
+ }
+
+ void EncryptionModeLRW::Encrypt (byte *data, uint64 length) const
+ {
+ ValidateState ();
+ EncryptBuffer (data, length, 1);
+ }
+
+ void EncryptionModeLRW::EncryptBuffer (byte *data, uint64 length, uint64 blockIndex) const
+ {
+ size_t blockSize = Ciphers.front()->GetBlockSize();
+ if (blockSize != 8 && blockSize != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ byte i[8];
+ *(uint64 *)i = Endian::Big (blockIndex);
+
+ byte t[Cipher::MaxBlockSize];
+
+ for (unsigned int b = 0; b < length / blockSize; b++)
+ {
+ if (blockSize == 8)
+ {
+ Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr()));
+ Xor64 ((uint64 *)data, (uint64 *)t);
+ }
+ else
+ {
+ Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr()));
+ Xor128 ((uint64 *)data, (uint64 *)t);
+ }
+
+ for (CipherList::const_iterator iCipherList = Ciphers.begin();
+ iCipherList != Ciphers.end();
+ ++iCipherList)
+ {
+ const Cipher &c = **iCipherList;
+
+ if (c.GetBlockSize () != blockSize)
+ throw ParameterIncorrect (SRC_POS);
+
+ c.EncryptBlock (data);
+ }
+
+ if (blockSize == 8)
+ Xor64 ((uint64 *)data, (uint64 *)t);
+ else
+ Xor128 ((uint64 *)data, (uint64 *)t);
+
+ data += blockSize;
+ IncrementBlockIndex (i);
+ }
+
+ Memory::Erase (t, sizeof (t));
+ }
+
+ void EncryptionModeLRW::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
+ {
+ if_debug (ValidateState ());
+ if_debug (ValidateParameters (data, sectorCount, sectorSize));
+
+ EncryptBuffer (data,
+ sectorCount * sectorSize,
+ SectorToBlockIndex (sectorIndex));
+ }
+
+ void EncryptionModeLRW::IncrementBlockIndex (byte *index) const
+ {
+ if (index[7] != 0xff)
+ index[7]++;
+ else
+ *(uint64 *)index = Endian::Big ( Endian::Big (*(uint64 *)index) + 1 );
+ }
+
+ uint64 EncryptionModeLRW::SectorToBlockIndex (uint64 sectorIndex) const
+ {
+ sectorIndex -= SectorOffset;
+
+ switch (Ciphers.front()->GetBlockSize())
+ {
+ case 8:
+ return (sectorIndex << 6) | 1;
+
+ case 16:
+ return (sectorIndex << 5) | 1;
+
+ default:
+ throw ParameterIncorrect (SRC_POS);
+ }
+ }
+
+ void EncryptionModeLRW::SetKey (const ConstBufferPtr &key)
+ {
+ if (key.Size() != 16)
+ throw ParameterIncorrect (SRC_POS);
+
+ if (!KeySet)
+ GfContext.Allocate (sizeof (GfCtx));
+
+ if (!Gf64TabInit ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr())))
+ throw bad_alloc();
+
+ if (!Gf128Tab64Init ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr())))
+ throw bad_alloc();
+
+ Key.CopyFrom (key);
+ KeySet = true;
+ }
+
+ void EncryptionModeLRW::Xor64 (uint64 *a, const uint64 *b) const
+ {
+ *a ^= *b;
+ }
+
+ void EncryptionModeLRW::Xor128 (uint64 *a, const uint64 *b) const
+ {
+ *a++ ^= *b++;
+ *a ^= *b;
+ }
+}
diff --git a/src/Volume/EncryptionModeLRW.h b/src/Volume/EncryptionModeLRW.h
new file mode 100644
index 00000000..97a8528d
--- /dev/null
+++ b/src/Volume/EncryptionModeLRW.h
@@ -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
diff --git a/src/Volume/EncryptionModeXTS.cpp b/src/Volume/EncryptionModeXTS.cpp
new file mode 100644
index 00000000..8073f3ca
--- /dev/null
+++ b/src/Volume/EncryptionModeXTS.cpp
@@ -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;
+ }
+}
diff --git a/src/Volume/EncryptionModeXTS.h b/src/Volume/EncryptionModeXTS.h
new file mode 100644
index 00000000..927a34cb
--- /dev/null
+++ b/src/Volume/EncryptionModeXTS.h
@@ -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
diff --git a/src/Volume/EncryptionTest.cpp b/src/Volume/EncryptionTest.cpp
new file mode 100644
index 00000000..cfede524
--- /dev/null
+++ b/src/Volume/EncryptionTest.cpp
@@ -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);
+ }
+}
diff --git a/src/Volume/EncryptionTest.h b/src/Volume/EncryptionTest.h
new file mode 100644
index 00000000..40221ae0
--- /dev/null
+++ b/src/Volume/EncryptionTest.h
@@ -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
diff --git a/src/Volume/EncryptionThreadPool.cpp b/src/Volume/EncryptionThreadPool.cpp
new file mode 100644
index 00000000..dbcc1b35
--- /dev/null
+++ b/src/Volume/EncryptionThreadPool.cpp
@@ -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;
+}
diff --git a/src/Volume/EncryptionThreadPool.h b/src/Volume/EncryptionThreadPool.h
new file mode 100644
index 00000000..70d87021
--- /dev/null
+++ b/src/Volume/EncryptionThreadPool.h
@@ -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
diff --git a/src/Volume/Hash.cpp b/src/Volume/Hash.cpp
new file mode 100644
index 00000000..cca8cc6b
--- /dev/null
+++ b/src/Volume/Hash.cpp
@@ -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());
+ }
+}
diff --git a/src/Volume/Hash.h b/src/Volume/Hash.h
new file mode 100644
index 00000000..3a24602c
--- /dev/null
+++ b/src/Volume/Hash.h
@@ -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
diff --git a/src/Volume/Keyfile.cpp b/src/Volume/Keyfile.cpp
new file mode 100644
index 00000000..d132dbb8
--- /dev/null
+++ b/src/Volume/Keyfile.cpp
@@ -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;
+}
diff --git a/src/Volume/Keyfile.h b/src/Volume/Keyfile.h
new file mode 100644
index 00000000..6d7a1a87
--- /dev/null
+++ b/src/Volume/Keyfile.h
@@ -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
diff --git a/src/Volume/Pkcs5Kdf.cpp b/src/Volume/Pkcs5Kdf.cpp
new file mode 100644
index 00000000..9f9a4d96
--- /dev/null
+++ b/src/Volume/Pkcs5Kdf.cpp
@@ -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());
+ }
+}
diff --git a/src/Volume/Pkcs5Kdf.h b/src/Volume/Pkcs5Kdf.h
new file mode 100644
index 00000000..a0b8f28a
--- /dev/null
+++ b/src/Volume/Pkcs5Kdf.h
@@ -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
diff --git a/src/Volume/Version.h b/src/Volume/Version.h
new file mode 100644
index 00000000..62738142
--- /dev/null
+++ b/src/Volume/Version.h
@@ -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
diff --git a/src/Volume/Volume.cpp b/src/Volume/Volume.cpp
new file mode 100644
index 00000000..0acdbb2e
--- /dev/null
+++ b/src/Volume/Volume.cpp
@@ -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;
+ }
+}
diff --git a/src/Volume/Volume.h b/src/Volume/Volume.h
new file mode 100644
index 00000000..8578bec1
--- /dev/null
+++ b/src/Volume/Volume.h
@@ -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
diff --git a/src/Volume/Volume.make b/src/Volume/Volume.make
new file mode 100644
index 00000000..29412a9f
--- /dev/null
+++ b/src/Volume/Volume.make
@@ -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
diff --git a/src/Volume/VolumeException.cpp b/src/Volume/VolumeException.cpp
new file mode 100644
index 00000000..2c143dae
--- /dev/null
+++ b/src/Volume/VolumeException.cpp
@@ -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);
+}
diff --git a/src/Volume/VolumeException.h b/src/Volume/VolumeException.h
new file mode 100644
index 00000000..2f312b7f
--- /dev/null
+++ b/src/Volume/VolumeException.h
@@ -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
diff --git a/src/Volume/VolumeHeader.cpp b/src/Volume/VolumeHeader.cpp
new file mode 100644
index 00000000..f31111cc
--- /dev/null
+++ b/src/Volume/VolumeHeader.cpp
@@ -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;
+ }
+}
diff --git a/src/Volume/VolumeHeader.h b/src/Volume/VolumeHeader.h
new file mode 100644
index 00000000..c16fc560
--- /dev/null
+++ b/src/Volume/VolumeHeader.h
@@ -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
diff --git a/src/Volume/VolumeInfo.cpp b/src/Volume/VolumeInfo.cpp
new file mode 100644
index 00000000..28c7f3f6
--- /dev/null
+++ b/src/Volume/VolumeInfo.cpp
@@ -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);
+}
diff --git a/src/Volume/VolumeInfo.h b/src/Volume/VolumeInfo.h
new file mode 100644
index 00000000..6e5f5dd4
--- /dev/null
+++ b/src/Volume/VolumeInfo.h
@@ -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
diff --git a/src/Volume/VolumeLayout.cpp b/src/Volume/VolumeLayout.cpp
new file mode 100644
index 00000000..00696e92
--- /dev/null
+++ b/src/Volume/VolumeLayout.cpp
@@ -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;
+ }
+}
diff --git a/src/Volume/VolumeLayout.h b/src/Volume/VolumeLayout.h
new file mode 100644
index 00000000..d2147425
--- /dev/null
+++ b/src/Volume/VolumeLayout.h
@@ -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
diff --git a/src/Volume/VolumePassword.cpp b/src/Volume/VolumePassword.cpp
new file mode 100644
index 00000000..86b17e22
--- /dev/null
+++ b/src/Volume/VolumePassword.cpp
@@ -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);
+}
diff --git a/src/Volume/VolumePassword.h b/src/Volume/VolumePassword.h
new file mode 100644
index 00000000..e43c50ec
--- /dev/null
+++ b/src/Volume/VolumePassword.h
@@ -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
diff --git a/src/Volume/VolumePasswordCache.cpp b/src/Volume/VolumePasswordCache.cpp
new file mode 100644
index 00000000..23472d2d
--- /dev/null
+++ b/src/Volume/VolumePasswordCache.cpp
@@ -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;
+}
diff --git a/src/Volume/VolumePasswordCache.h b/src/Volume/VolumePasswordCache.h
new file mode 100644
index 00000000..6d5118af
--- /dev/null
+++ b/src/Volume/VolumePasswordCache.h
@@ -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
diff --git a/src/Volume/VolumeSlot.h b/src/Volume/VolumeSlot.h
new file mode 100644
index 00000000..fe368772
--- /dev/null
+++ b/src/Volume/VolumeSlot.h
@@ -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