From d5dca62b044290475d9dd793e4abb58fbfe776d5 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 11 Jun 2018 00:12:32 +0200 Subject: Linux/MacOSX/FreeBSD: Support mounting partially encrypted system partitions/drivers in ReadOnly mode in order to allow troubleshooting in some cases. --- src/Core/Unix/Linux/CoreLinux.cpp | 1 + src/Volume/Volume.cpp | 40 ++++++++++++++++++++++++++++++++++++--- src/Volume/Volume.h | 4 ++++ 3 files changed, 42 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Core/Unix/Linux/CoreLinux.cpp b/src/Core/Unix/Linux/CoreLinux.cpp index 0fa97f64..7f18fff4 100644 --- a/src/Core/Unix/Linux/CoreLinux.cpp +++ b/src/Core/Unix/Linux/CoreLinux.cpp @@ -313,6 +313,7 @@ namespace VeraCrypt if (options.NoKernelCrypto || !xts || algoNotSupported + || volume->IsEncryptionNotCompleted () || volume->GetProtectionType() == VolumeProtection::HiddenVolumeReadOnly) { throw NotApplicable (SRC_POS); diff --git a/src/Volume/Volume.cpp b/src/Volume/Volume.cpp index d3ef2067..d4d799d1 100644 --- a/src/Volume/Volume.cpp +++ b/src/Volume/Volume.cpp @@ -24,12 +24,15 @@ 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) { } @@ -206,6 +209,7 @@ namespace VeraCrypt VolumeDataOffset = layout->GetDataOffset (VolumeHostSize); VolumeDataSize = layout->GetDataSize (VolumeHostSize); + EncryptedDataSize = header->GetEncryptedAreaLength(); Header = header; Layout = layout; @@ -215,7 +219,11 @@ 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(); @@ -223,6 +231,8 @@ namespace VeraCrypt || partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength()) throw PasswordIncorrect (SRC_POS); + EncryptedDataSize -= partitionStartOffset - header->GetEncryptedAreaStart(); + mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE); } @@ -313,7 +323,31 @@ namespace VeraCrypt if (VolumeFile->ReadAt (buffer, hostOffset) != length) throw MissingVolumeData (SRC_POS); - EA->DecryptSectors (buffer, hostOffset / SectorSize, length / SectorSize, SectorSize); + if (EncryptionNotCompleted) + { + // if encryption is not complete, we decrypt only the encrypted sectors + if (hostOffset < EncryptedDataSize) + { + size_t bufferOffset = 0; + + // first sector is not encrypted in case of incomplete encryption + if (hostOffset == 0) + { + bufferOffset = (size_t) SectorSize; + hostOffset += SectorSize; + length -= SectorSize; + } + + if (length && (hostOffset < EncryptedDataSize)) + { + uint64 encryptedLength = VC_MIN (length, (EncryptedDataSize - hostOffset)); + + EA->DecryptSectors (buffer.GetRange (bufferOffset, encryptedLength), hostOffset / SectorSize, encryptedLength / SectorSize, SectorSize); + } + } + } + else + EA->DecryptSectors (buffer, hostOffset / SectorSize, length / SectorSize, SectorSize); TotalDataRead += length; } diff --git a/src/Volume/Volume.h b/src/Volume/Volume.h index 311c65bc..a743a161 100644 --- a/src/Volume/Volume.h +++ b/src/Volume/Volume.h @@ -113,6 +113,7 @@ namespace VeraCrypt uint32 GetSaltSize () const { return Header->GetSaltSize(); } size_t GetSectorSize () const { return SectorSize; } uint64 GetSize () const { return VolumeDataSize; } + uint64 GetEncryptedSize () const { return EncryptedDataSize; } uint64 GetTopWriteOffset () const { return TopWriteOffset; } uint64 GetTotalDataRead () const { return TotalDataRead; } uint64 GetTotalDataWritten () const { return TotalDataWritten; } @@ -127,6 +128,7 @@ namespace VeraCrypt 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); + bool IsEncryptionNotCompleted () const { return EncryptionNotCompleted; } protected: void CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength); @@ -146,11 +148,13 @@ namespace VeraCrypt uint64 VolumeHostSize; uint64 VolumeDataOffset; uint64 VolumeDataSize; + uint64 EncryptedDataSize; uint64 TopWriteOffset; uint64 TotalDataRead; uint64 TotalDataWritten; bool TrueCryptMode; int Pim; + bool EncryptionNotCompleted; private: Volume (const Volume &); -- cgit v1.2.3