diff options
Diffstat (limited to 'src/Volume/Volume.cpp')
-rw-r--r-- | src/Volume/Volume.cpp | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/src/Volume/Volume.cpp b/src/Volume/Volume.cpp index e9bf40c0..524f2395 100644 --- a/src/Volume/Volume.cpp +++ b/src/Volume/Volume.cpp @@ -3,9 +3,9 @@ Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) - and all other portions of this file are Copyright (c) 2013-2016 IDRIX + and all other portions of this file are Copyright (c) 2013-2017 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ @@ -23,14 +23,16 @@ namespace VeraCrypt { Volume::Volume () : HiddenVolumeProtectionTriggered (false), SystemEncryption (false), + VolumeDataOffset (0), VolumeDataSize (0), + EncryptedDataSize (0), TopWriteOffset (0), TotalDataRead (0), TotalDataWritten (0), - TrueCryptMode (false), - Pim (0) + Pim (0), + EncryptionNotCompleted (false) { } Volume::~Volume () @@ -67,9 +69,9 @@ namespace VeraCrypt if_debug (ValidateState ()); return EA->GetMode(); } - void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { make_shared_auto (File, file); File::FileOpenFlags flags = (preserveTimestamps ? File::PreserveTimestamps : File::FlagsNone); @@ -98,28 +100,24 @@ namespace VeraCrypt else throw; } - return Open (file, password, pim, kdf, truecryptMode, keyfiles, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + return Open (file, password, pim, kdf, keyfiles, emvSupportEnabled, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); } - void Volume::Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf,shared_ptr <KeyfileList> protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf,shared_ptr <KeyfileList> protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { if (!volumeFile) throw ParameterIncorrect (SRC_POS); - // TrueCrypt doesn't support SHA-256 - if (kdf && truecryptMode && (kdf->GetName() == L"HMAC-SHA-256")) - throw UnsupportedAlgoInTrueCryptMode (SRC_POS); - Protection = protection; VolumeFile = volumeFile; SystemEncryption = partitionInSystemEncryptionScope; try { VolumeHostSize = VolumeFile->Length(); - shared_ptr <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (keyfiles, password); + shared_ptr <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (keyfiles, password, emvSupportEnabled); bool skipLayoutV1Normal = false; // Test volume layouts @@ -186,27 +184,27 @@ namespace VeraCrypt } shared_ptr <VolumeHeader> header = layout->GetHeader(); - if (header->Decrypt (headerBuffer, *passwordKey, pim, kdf, truecryptMode, layout->GetSupportedKeyDerivationFunctions(truecryptMode), layoutEncryptionAlgorithms, layoutEncryptionModes)) + if (header->Decrypt (headerBuffer, *passwordKey, pim, kdf, layout->GetSupportedKeyDerivationFunctions(), layoutEncryptionAlgorithms, layoutEncryptionModes)) { // Header decrypted - if (!truecryptMode && typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x10b) + if (typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x10b) { // VolumeLayoutV1Normal has been opened as VolumeLayoutV2Normal layout.reset (new VolumeLayoutV1Normal); header->SetSize (layout->GetHeaderSize()); layout->SetHeader (header); } - TrueCryptMode = truecryptMode; Pim = pim; Type = layout->GetType(); SectorSize = header->GetSectorSize(); VolumeDataOffset = layout->GetDataOffset (VolumeHostSize); VolumeDataSize = layout->GetDataSize (VolumeHostSize); + EncryptedDataSize = header->GetEncryptedAreaLength(); Header = header; Layout = layout; EA = header->GetEncryptionAlgorithm(); @@ -214,16 +212,22 @@ namespace VeraCrypt if (layout->HasDriveHeader()) { if (header->GetEncryptedAreaLength() != header->GetVolumeDataSize()) - throw VolumeEncryptionNotCompleted (SRC_POS); + { + EncryptionNotCompleted = true; + // we avoid writing data to the partition since it is only partially encrypted + Protection = VolumeProtection::ReadOnly; + } uint64 partitionStartOffset = VolumeFile->GetPartitionDeviceStartOffset(); if (partitionStartOffset < header->GetEncryptedAreaStart() || partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength()) throw PasswordIncorrect (SRC_POS); + EncryptedDataSize -= partitionStartOffset - header->GetEncryptedAreaStart(); + mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE); } // Volume protection @@ -237,9 +241,10 @@ namespace VeraCrypt { Volume protectedVolume; protectedVolume.Open (VolumeFile, - protectionPassword, protectionPim, protectionKdf, truecryptMode, protectionKeyfiles, + protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, + emvSupportEnabled, VolumeProtection::ReadOnly, shared_ptr <VolumePassword> (), 0, shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> (), VolumeType::Hidden, useBackupHeaders); @@ -275,10 +280,10 @@ namespace VeraCrypt Buffer mbr (VolumeFile->GetDeviceSectorSize()); driveDevice.ReadAt (mbr, 0); - // Search for the string "VeraCrypt" or "TrueCrypt" - const char* bootSignature = truecryptMode? "TrueCrypt" : TC_APP_NAME; + // Search for the string "VeraCrypt" + const char* bootSignature = TC_APP_NAME; size_t nameLen = strlen (bootSignature); for (size_t i = 0; i < mbr.Size() - nameLen; ++i) { if (memcmp (mbr.Ptr() + i, bootSignature, nameLen) == 0) @@ -305,16 +310,40 @@ namespace VeraCrypt if_debug (ValidateState ()); uint64 length = buffer.Size(); uint64 hostOffset = VolumeDataOffset + byteOffset; + size_t bufferOffset = 0; 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); + // first sector can be unencrypted in some cases (e.g. windows repair) + // detect this case by looking for NTFS header + if (SystemEncryption && (hostOffset == 0) && ((BE64 (*(uint64 *) buffer.Get ())) == 0xEB52904E54465320ULL)) + { + bufferOffset = (size_t) SectorSize; + hostOffset += SectorSize; + length -= SectorSize; + } + + if (length) + { + if (EncryptionNotCompleted) + { + // if encryption is not complete, we decrypt only the encrypted sectors + if (hostOffset < EncryptedDataSize) + { + uint64 encryptedLength = VC_MIN (length, (EncryptedDataSize - hostOffset)); + + EA->DecryptSectors (buffer.GetRange (bufferOffset, encryptedLength), hostOffset / SectorSize, encryptedLength / SectorSize, SectorSize); + } + } + else + EA->DecryptSectors (buffer.GetRange (bufferOffset, length), hostOffset / SectorSize, length / SectorSize, SectorSize); + } TotalDataRead += length; } |