From 3cb7fdea950dd2d0377f0d9ad8a88fcb7c48b842 Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Wed, 14 Jul 2021 11:27:03 +1200 Subject: Initial mirror commit --- Volume/Cipher.cpp | 314 ++++++++++++++ Volume/Cipher.h | 129 ++++++ Volume/Crc32.h | 44 ++ Volume/EncryptionAlgorithm.cpp | 345 ++++++++++++++++ Volume/EncryptionAlgorithm.h | 93 +++++ Volume/EncryptionMode.cpp | 63 +++ Volume/EncryptionMode.h | 62 +++ Volume/EncryptionModeCBC.cpp | 335 +++++++++++++++ Volume/EncryptionModeCBC.h | 47 +++ Volume/EncryptionModeLRW.cpp | 195 +++++++++ Volume/EncryptionModeLRW.h | 50 +++ Volume/EncryptionModeXTS.cpp | 374 +++++++++++++++++ Volume/EncryptionModeXTS.h | 50 +++ Volume/EncryptionTest.cpp | 890 ++++++++++++++++++++++++++++++++++++++++ Volume/EncryptionTest.h | 50 +++ Volume/EncryptionThreadPool.cpp | 325 +++++++++++++++ Volume/EncryptionThreadPool.h | 87 ++++ Volume/Hash.cpp | 138 +++++++ Volume/Hash.h | 135 ++++++ Volume/Keyfile.cpp | 181 ++++++++ Volume/Keyfile.h | 49 +++ Volume/Pkcs5Kdf.cpp | 96 +++++ Volume/Pkcs5Kdf.h | 127 ++++++ Volume/Version.h | 25 ++ Volume/Volume.cpp | 388 ++++++++++++++++++ Volume/Volume.h | 126 ++++++ Volume/Volume.make | 62 +++ Volume/VolumeException.cpp | 32 ++ Volume/VolumeException.h | 43 ++ Volume/VolumeHeader.cpp | 340 +++++++++++++++ Volume/VolumeHeader.h | 126 ++++++ Volume/VolumeInfo.cpp | 118 ++++++ Volume/VolumeInfo.h | 66 +++ Volume/VolumeLayout.cpp | 254 ++++++++++++ Volume/VolumeLayout.h | 153 +++++++ Volume/VolumePassword.cpp | 167 ++++++++ Volume/VolumePassword.h | 92 +++++ Volume/VolumePasswordCache.cpp | 43 ++ Volume/VolumePasswordCache.h | 36 ++ Volume/VolumeSlot.h | 19 + 40 files changed, 6269 insertions(+) create mode 100644 Volume/Cipher.cpp create mode 100644 Volume/Cipher.h create mode 100644 Volume/Crc32.h create mode 100644 Volume/EncryptionAlgorithm.cpp create mode 100644 Volume/EncryptionAlgorithm.h create mode 100644 Volume/EncryptionMode.cpp create mode 100644 Volume/EncryptionMode.h create mode 100644 Volume/EncryptionModeCBC.cpp create mode 100644 Volume/EncryptionModeCBC.h create mode 100644 Volume/EncryptionModeLRW.cpp create mode 100644 Volume/EncryptionModeLRW.h create mode 100644 Volume/EncryptionModeXTS.cpp create mode 100644 Volume/EncryptionModeXTS.h create mode 100644 Volume/EncryptionTest.cpp create mode 100644 Volume/EncryptionTest.h create mode 100644 Volume/EncryptionThreadPool.cpp create mode 100644 Volume/EncryptionThreadPool.h create mode 100644 Volume/Hash.cpp create mode 100644 Volume/Hash.h create mode 100644 Volume/Keyfile.cpp create mode 100644 Volume/Keyfile.h create mode 100644 Volume/Pkcs5Kdf.cpp create mode 100644 Volume/Pkcs5Kdf.h create mode 100644 Volume/Version.h create mode 100644 Volume/Volume.cpp create mode 100644 Volume/Volume.h create mode 100644 Volume/Volume.make create mode 100644 Volume/VolumeException.cpp create mode 100644 Volume/VolumeException.h create mode 100644 Volume/VolumeHeader.cpp create mode 100644 Volume/VolumeHeader.h create mode 100644 Volume/VolumeInfo.cpp create mode 100644 Volume/VolumeInfo.h create mode 100644 Volume/VolumeLayout.cpp create mode 100644 Volume/VolumeLayout.h create mode 100644 Volume/VolumePassword.cpp create mode 100644 Volume/VolumePassword.h create mode 100644 Volume/VolumePasswordCache.cpp create mode 100644 Volume/VolumePasswordCache.h create mode 100644 Volume/VolumeSlot.h (limited to 'Volume') diff --git a/Volume/Cipher.cpp b/Volume/Cipher.cpp new file mode 100644 index 0000000..fa37e29 --- /dev/null +++ b/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 (new CipherAES ())); + l.push_back (shared_ptr (new CipherSerpent ())); + l.push_back (shared_ptr (new CipherTwofish ())); + l.push_back (shared_ptr (new CipherBlowfish ())); + l.push_back (shared_ptr (new CipherCast5 ())); + l.push_back (shared_ptr (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 (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 (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 (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 (GetKeySize ()) * 8); + } + + + bool Cipher::HwSupportEnabled = true; +} diff --git a/Volume/Cipher.h b/Volume/Cipher.h new file mode 100644 index 0000000..25fc82c --- /dev/null +++ b/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 > 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 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 GetNew () const { return shared_ptr (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/Volume/Crc32.h b/Volume/Crc32.h new file mode 100644 index 0000000..d439227 --- /dev/null +++ b/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 (buffer.Get()), static_cast (buffer.Size())); + } + + protected: + uint32 CrcValue; + + private: + Crc32 (const Crc32 &); + Crc32 &operator= (const Crc32 &); + }; +} + +#endif // TC_HEADER_Encryption_Crc32 diff --git a/Volume/EncryptionAlgorithm.cpp b/Volume/EncryptionAlgorithm.cpp new file mode 100644 index 0000000..5ca27ba --- /dev/null +++ b/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 (new AES ())); + l.push_back (shared_ptr (new Serpent ())); + l.push_back (shared_ptr (new Twofish ())); + l.push_back (shared_ptr (new AESTwofish ())); + l.push_back (shared_ptr (new AESTwofishSerpent ())); + l.push_back (shared_ptr (new SerpentAES ())); + l.push_back (shared_ptr (new SerpentTwofishAES ())); + l.push_back (shared_ptr (new TwofishSerpent ())); + + l.push_back (shared_ptr (new AESBlowfish ())); + l.push_back (shared_ptr (new AESBlowfishSerpent ())); + l.push_back (shared_ptr (new Blowfish ())); + l.push_back (shared_ptr (new Cast5 ())); + l.push_back (shared_ptr (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 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 mode) const + { + return IsModeSupported (*mode); + } + + void EncryptionAlgorithm::SetMode (shared_ptr 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 (new CipherAES())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Blowfish + AESBlowfish::AESBlowfish () + { + Deprecated = true; + + Ciphers.push_back (shared_ptr (new CipherBlowfish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Blowfish-Serpent + AESBlowfishSerpent::AESBlowfishSerpent () + { + Deprecated = true; + + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherBlowfish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Twofish + AESTwofish::AESTwofish () + { + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Twofish-Serpent + AESTwofishSerpent::AESTwofishSerpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Blowfish + Blowfish::Blowfish () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherBlowfish())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // CAST5 + Cast5::Cast5 () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherCast5())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent + Serpent::Serpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent-AES + SerpentAES::SerpentAES () + { + Ciphers.push_back (shared_ptr (new CipherAES ())); + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Triple-DES + TripleDES::TripleDES () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherTripleDES())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Twofish + Twofish::Twofish () + { + Ciphers.push_back (shared_ptr (new CipherTwofish())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Twofish-Serpent + TwofishSerpent::TwofishSerpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent-Twofish-AES + SerpentTwofishAES::SerpentTwofishAES () + { + Ciphers.push_back (shared_ptr (new CipherAES ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } +} diff --git a/Volume/EncryptionAlgorithm.h b/Volume/EncryptionAlgorithm.h new file mode 100644 index 0000000..8118de6 --- /dev/null +++ b/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 > 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 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 GetMode () const; + virtual wstring GetName () const; + bool IsDeprecated () const { return Deprecated; } + virtual bool IsModeSupported (const EncryptionMode &mode) const; + virtual bool IsModeSupported (const shared_ptr mode) const; + virtual void SetKey (const ConstBufferPtr &key); + virtual void SetMode (shared_ptr mode); + + protected: + EncryptionAlgorithm (); + + void ValidateState () const; + + CipherList Ciphers; + bool Deprecated; + shared_ptr 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 GetNew () const { return shared_ptr (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/Volume/EncryptionMode.cpp b/Volume/EncryptionMode.cpp new file mode 100644 index 0000000..eb68186 --- /dev/null +++ b/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 (new EncryptionModeXTS ())); + l.push_back (shared_ptr (new EncryptionModeLRW ())); + l.push_back (shared_ptr (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/Volume/EncryptionMode.h b/Volume/EncryptionMode.h new file mode 100644 index 0000000..e74fca5 --- /dev/null +++ b/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 > 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 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/Volume/EncryptionModeCBC.cpp b/Volume/EncryptionModeCBC.cpp new file mode 100644 index 0000000..f299b88 --- /dev/null +++ b/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/Volume/EncryptionModeCBC.h b/Volume/EncryptionModeCBC.h new file mode 100644 index 0000000..3e1094a --- /dev/null +++ b/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 GetNew () const { return shared_ptr (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/Volume/EncryptionModeLRW.cpp b/Volume/EncryptionModeLRW.cpp new file mode 100644 index 0000000..38731d5 --- /dev/null +++ b/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/Volume/EncryptionModeLRW.h b/Volume/EncryptionModeLRW.h new file mode 100644 index 0000000..97a8528 --- /dev/null +++ b/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 GetNew () const { return shared_ptr (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/Volume/EncryptionModeXTS.cpp b/Volume/EncryptionModeXTS.cpp new file mode 100644 index 0000000..8073f3c --- /dev/null +++ b/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/Volume/EncryptionModeXTS.h b/Volume/EncryptionModeXTS.h new file mode 100644 index 0000000..927a34c --- /dev/null +++ b/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 GetNew () const { return shared_ptr (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/Volume/EncryptionTest.cpp b/Volume/EncryptionTest.cpp new file mode 100644 index 0000000..cfede52 --- /dev/null +++ b/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 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 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 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 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/Volume/EncryptionTest.h b/Volume/EncryptionTest.h new file mode 100644 index 0000000..40221ae --- /dev/null +++ b/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/Volume/EncryptionThreadPool.cpp b/Volume/EncryptionThreadPool.cpp new file mode 100644 index 0000000..dbcc1b3 --- /dev/null +++ b/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 +#endif + +#ifdef TC_MACOSX +# include +# include +#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 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 > EncryptionThreadPool::RunningThreads; +} diff --git a/Volume/EncryptionThreadPool.h b/Volume/EncryptionThreadPool.h new file mode 100644 index 0000000..70d8702 --- /dev/null +++ b/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 ItemException; + SyncEvent ItemCompletedEvent; + SharedVal OutstandingFragmentCount; + SharedVal 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 > 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/Volume/Hash.cpp b/Volume/Hash.cpp new file mode 100644 index 0000000..cca8cc6 --- /dev/null +++ b/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 (new Ripemd160 ())); + l.push_back (shared_ptr (new Sha512 ())); + l.push_back (shared_ptr (new Whirlpool ())); + l.push_back (shared_ptr (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/Volume/Hash.h b/Volume/Hash.h new file mode 100644 index 0000000..3a24602 --- /dev/null +++ b/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 > 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 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 GetNew () const { return shared_ptr (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 GetNew () const { return shared_ptr (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 GetNew () const { return shared_ptr (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 GetNew () const { return shared_ptr (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/Volume/Keyfile.cpp b/Volume/Keyfile.cpp new file mode 100644 index 0000000..d132dbb --- /dev/null +++ b/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 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 Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password) + { + if (!password) + password.reset (new VolumePassword); + + if (!keyfiles || keyfiles->size() < 1) + return password; + + KeyfileList keyfilesExp; + HiddenFileWasPresentInKeyfilePath = false; + + // Enumerate directories + foreach (shared_ptr 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 (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 Keyfile::DeserializeList (shared_ptr stream, const string &name) + { + shared_ptr 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 (k)); + } + return keyfiles; + } + + void Keyfile::SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles) + { + Serializer sr (stream); + sr.Serialize (name + "Null", keyfiles == nullptr); + if (keyfiles) + { + list sl; + + foreach_ref (const Keyfile &k, *keyfiles) + sl.push_back (FilesystemPath (k)); + + sr.Serialize (name, sl); + } + } + + bool Keyfile::HiddenFileWasPresentInKeyfilePath = false; +} diff --git a/Volume/Keyfile.h b/Volume/Keyfile.h new file mode 100644 index 0000000..6d7a1a8 --- /dev/null +++ b/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 > KeyfileList; + + class Keyfile + { + public: + Keyfile (const FilesystemPath &path) : Path (path) { } + virtual ~Keyfile () { }; + + operator FilesystemPath () const { return Path; } + static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password); + static shared_ptr DeserializeList (shared_ptr stream, const string &name); + static void SerializeList (shared_ptr stream, const string &name, shared_ptr 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/Volume/Pkcs5Kdf.cpp b/Volume/Pkcs5Kdf.cpp new file mode 100644 index 0000000..9f9a4d9 --- /dev/null +++ b/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::GetAlgorithm (const wstring &name) + { + foreach (shared_ptr kdf, GetAvailableAlgorithms()) + { + if (kdf->GetName() == name) + return kdf; + } + throw ParameterIncorrect (SRC_POS); + } + + shared_ptr Pkcs5Kdf::GetAlgorithm (const Hash &hash) + { + foreach (shared_ptr kdf, GetAvailableAlgorithms()) + { + if (typeid (*kdf->GetHash()) == typeid (hash)) + return kdf; + } + + throw ParameterIncorrect (SRC_POS); + } + + Pkcs5KdfList Pkcs5Kdf::GetAvailableAlgorithms () + { + Pkcs5KdfList l; + + l.push_back (shared_ptr (new Pkcs5HmacRipemd160 ())); + l.push_back (shared_ptr (new Pkcs5HmacSha512 ())); + l.push_back (shared_ptr (new Pkcs5HmacWhirlpool ())); + l.push_back (shared_ptr (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/Volume/Pkcs5Kdf.h b/Volume/Pkcs5Kdf.h new file mode 100644 index 0000000..a0b8f28 --- /dev/null +++ b/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 > 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 GetAlgorithm (const wstring &name); + static shared_ptr GetAlgorithm (const Hash &hash); + static Pkcs5KdfList GetAvailableAlgorithms (); + virtual shared_ptr 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 GetHash () const { return shared_ptr (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 GetHash () const { return shared_ptr (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 GetHash () const { return shared_ptr (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 GetHash () const { return shared_ptr (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 GetHash () const { return shared_ptr (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/Volume/Version.h b/Volume/Version.h new file mode 100644 index 0000000..6273814 --- /dev/null +++ b/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/Volume/Volume.cpp b/Volume/Volume.cpp new file mode 100644 index 0000000..0acdbb2 --- /dev/null +++ b/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 +#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 Volume::GetEncryptionAlgorithm () const + { + if_debug (ValidateState ()); + return EA; + } + + shared_ptr Volume::GetEncryptionMode () const + { + if_debug (ValidateState ()); + return EA->GetMode(); + } + + void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr 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 volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr 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 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 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 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 (), shared_ptr (), + 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 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/Volume/Volume.h b/Volume/Volume.h new file mode 100644 index 0000000..8578bec --- /dev/null +++ b/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 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 GetEncryptionAlgorithm () const; + shared_ptr GetEncryptionMode () const; + shared_ptr GetFile () const { return VolumeFile; } + shared_ptr GetHeader () const { return Header; } + uint64 GetHeaderCreationTime () const { return Header->GetHeaderCreationTime(); } + uint64 GetHostSize () const { return VolumeHostSize; } + shared_ptr GetLayout () const { return Layout; } + VolumePath GetPath () const { return VolumeFile->GetPath(); } + VolumeProtection::Enum GetProtectionType () const { return Protection; } + shared_ptr 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 password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (shared_ptr volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), 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 newPkcs5Kdf); + void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset); + + protected: + void CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength); + void ValidateState () const; + + shared_ptr EA; + shared_ptr Header; + bool HiddenVolumeProtectionTriggered; + shared_ptr Layout; + uint64 ProtectedRangeStart; + uint64 ProtectedRangeEnd; + VolumeProtection::Enum Protection; + size_t SectorSize; + bool SystemEncryption; + VolumeType::Enum Type; + shared_ptr 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/Volume/Volume.make b/Volume/Volume.make new file mode 100644 index 0000000..29412a9 --- /dev/null +++ b/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/Volume/VolumeException.cpp b/Volume/VolumeException.cpp new file mode 100644 index 0000000..2c143da --- /dev/null +++ b/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/Volume/VolumeException.h b/Volume/VolumeException.h new file mode 100644 index 0000000..2f312b7 --- /dev/null +++ b/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/Volume/VolumeHeader.cpp b/Volume/VolumeHeader.cpp new file mode 100644 index 0000000..f31111c --- /dev/null +++ b/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 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 pkcs5, keyDerivationFunctions) + { + pkcs5->DeriveKey (headerKey, password, salt); + + foreach (shared_ptr mode, encryptionModes) + { + if (typeid (*mode) != typeid (EncryptionModeXTS)) + mode->SetKey (headerKey.GetRange (0, mode->GetKeySize())); + + foreach (shared_ptr 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 &ea, shared_ptr &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 (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 (header, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) + { + return false; + } + + RequiredMinProgramVersion = DeserializeEntry (header, offset); + + if (RequiredMinProgramVersion > Version::Number()) + throw HigherVersionRequired (SRC_POS); + + VolumeKeyAreaCrc32 = DeserializeEntry (header, offset); + VolumeCreationTime = DeserializeEntry (header, offset); + HeaderCreationTime = DeserializeEntry (header, offset); + HiddenVolumeDataSize = DeserializeEntry (header, offset); + mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal); + VolumeDataSize = DeserializeEntry (header, offset); + EncryptedAreaStart = DeserializeEntry (header, offset); + EncryptedAreaLength = DeserializeEntry (header, offset); + Flags = DeserializeEntry (header, offset); + + SectorSize = DeserializeEntry (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 + 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 (header.Get() + offset - sizeof (T))); + } + + template + T VolumeHeader::DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const + { + if (offset > header.Size()) + throw ParameterIncorrect (SRC_POS); + + return Endian::Big (*reinterpret_cast (header.Get() + offset)); + } + + void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf) + { + if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize) + throw ParameterIncorrect (SRC_POS); + + shared_ptr mode = EA->GetMode()->GetNew(); + shared_ptr 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 + 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 (header.Get() + offset - sizeof (T)) = Endian::Big (entry); + } + + void VolumeHeader::SetSize (uint32 headerSize) + { + HeaderSize = headerSize; + EncryptedHeaderDataSize = HeaderSize - EncryptedHeaderDataOffset; + } +} diff --git a/Volume/VolumeHeader.h b/Volume/VolumeHeader.h new file mode 100644 index 0000000..c16fc56 --- /dev/null +++ b/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 EA; + shared_ptr 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 newPkcs5Kdf); + uint64 GetEncryptedAreaStart () const { return EncryptedAreaStart; } + uint64 GetEncryptedAreaLength () const { return EncryptedAreaLength; } + shared_ptr 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 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 &ea, shared_ptr &mode); + template T DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const; + template T DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const; + void Init (); + void Serialize (const BufferPtr &header) const; + template 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 EA; + shared_ptr 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/Volume/VolumeInfo.cpp b/Volume/VolumeInfo.cpp new file mode 100644 index 0000000..28c7f3f --- /dev/null +++ b/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) + { + 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 (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 (sr.DeserializeInt32 ("Type")); + VirtualDevice = sr.DeserializeWString ("VirtualDevice"); + sr.Deserialize ("VolumeCreationTime", VolumeCreationTime); + } + + bool VolumeInfo::FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr second) + { + return first->SerialInstanceNumber > second->SerialInstanceNumber; + } + + void VolumeInfo::Serialize (shared_ptr 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 (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 (Type)); + sr.Serialize ("VirtualDevice", wstring (VirtualDevice)); + sr.Serialize ("VolumeCreationTime", VolumeCreationTime); + } + + void VolumeInfo::Set (const Volume &volume) + { + EncryptionAlgorithmBlockSize = static_cast (volume.GetEncryptionAlgorithm()->GetMaxBlockSize()); + EncryptionAlgorithmKeySize = static_cast (volume.GetEncryptionAlgorithm()->GetKeySize()); + EncryptionAlgorithmMinBlockSize = static_cast (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/Volume/VolumeInfo.h b/Volume/VolumeInfo.h new file mode 100644 index 0000000..6e5f5dd --- /dev/null +++ b/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 > VolumeInfoList; + + class VolumeInfo : public Serializable + { + public: + VolumeInfo () { } + virtual ~VolumeInfo () { } + + TC_SERIALIZABLE (VolumeInfo); + static bool FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr 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/Volume/VolumeLayout.cpp b/Volume/VolumeLayout.cpp new file mode 100644 index 0000000..00696e9 --- /dev/null +++ b/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 (new VolumeLayoutV2Normal ())); + layouts.push_back (shared_ptr (new VolumeLayoutV1Normal ())); + layouts.push_back (shared_ptr (new VolumeLayoutV2Hidden ())); + layouts.push_back (shared_ptr (new VolumeLayoutV1Hidden ())); + layouts.push_back (shared_ptr (new VolumeLayoutSystemEncryption ())); + + if (type != VolumeType::Unknown) + { + VolumeLayoutList l; + + foreach (shared_ptr vl, layouts) + { + if (vl->GetType() == type) + l.push_back (vl); + } + + layouts = l; + } + + return layouts; + } + + shared_ptr 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 (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedEncryptionModes.push_back (shared_ptr (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 (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedEncryptionModes.push_back (shared_ptr (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 (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (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 (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (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 (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (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 (new Pkcs5HmacRipemd160_1000 ())); + return l; + } +} diff --git a/Volume/VolumeLayout.h b/Volume/VolumeLayout.h new file mode 100644 index 0000000..d214742 --- /dev/null +++ b/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 > 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 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 header) { Header = header; } + + protected: + VolumeLayout (); + + EncryptionAlgorithmList SupportedEncryptionAlgorithms; + EncryptionModeList SupportedEncryptionModes; + + int BackupHeaderOffset; + int HeaderOffset; + uint32 HeaderSize; + VolumeType::Enum Type; + + shared_ptr 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/Volume/VolumePassword.cpp b/Volume/VolumePassword.cpp new file mode 100644 index 0000000..86b17e2 --- /dev/null +++ b/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) + { + Serializer sr (stream); + uint64 passwordSize; + sr.Deserialize ("PasswordSize", passwordSize); + PasswordSize = static_cast (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) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("PasswordSize", static_cast (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/Volume/VolumePassword.h b/Volume/VolumePassword.h new file mode 100644 index 0000000..e43c50e --- /dev/null +++ b/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/Volume/VolumePasswordCache.cpp b/Volume/VolumePasswordCache.cpp new file mode 100644 index 0000000..23472d2 --- /dev/null +++ b/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 (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 (newPassword))); + + if (CachedPasswords.size() > Capacity) + CachedPasswords.pop_back(); + } + + CachedPasswordList VolumePasswordCache::CachedPasswords; +} diff --git a/Volume/VolumePasswordCache.h b/Volume/VolumePasswordCache.h new file mode 100644 index 0000000..6d5118a --- /dev/null +++ b/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/Volume/VolumeSlot.h b/Volume/VolumeSlot.h new file mode 100644 index 0000000..fe36877 --- /dev/null +++ b/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 -- cgit