"Fossies" - the Fresh Open Source Software Archive

Member "src/Volume/Volume.cpp" (10 Oct 2018, 13322 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Volume.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #ifndef TC_WINDOWS
   14 #include <errno.h>
   15 #endif
   16 #include "EncryptionModeXTS.h"
   17 #include "Volume.h"
   18 #include "VolumeHeader.h"
   19 #include "VolumeLayout.h"
   20 #include "Common/Crypto.h"
   21 
   22 namespace VeraCrypt
   23 {
   24     Volume::Volume ()
   25         : HiddenVolumeProtectionTriggered (false),
   26         SystemEncryption (false),
   27         VolumeDataOffset (0),
   28         VolumeDataSize (0),
   29         EncryptedDataSize (0),
   30         TopWriteOffset (0),
   31         TotalDataRead (0),
   32         TotalDataWritten (0),
   33         TrueCryptMode (false),
   34         Pim (0),
   35         EncryptionNotCompleted (false)
   36     {
   37     }
   38 
   39     Volume::~Volume ()
   40     {
   41     }
   42 
   43     void Volume::CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength)
   44     {
   45         uint64 writeHostEndOffset = writeHostOffset + writeLength - 1;
   46 
   47         if ((writeHostOffset < ProtectedRangeStart) ? (writeHostEndOffset >= ProtectedRangeStart) : (writeHostOffset <= ProtectedRangeEnd - 1))
   48         {
   49             HiddenVolumeProtectionTriggered = true;
   50             throw VolumeProtected (SRC_POS);
   51         }
   52     }
   53 
   54     void Volume::Close ()
   55     {
   56         if (VolumeFile.get() == nullptr)
   57             throw NotInitialized (SRC_POS);
   58 
   59         VolumeFile.reset();
   60     }
   61 
   62     shared_ptr <EncryptionAlgorithm> Volume::GetEncryptionAlgorithm () const
   63     {
   64         if_debug (ValidateState ());
   65         return EA;
   66     }
   67 
   68     shared_ptr <EncryptionMode> Volume::GetEncryptionMode () const
   69     {
   70         if_debug (ValidateState ());
   71         return EA->GetMode();
   72     }
   73 
   74     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)
   75     {
   76         make_shared_auto (File, file);
   77 
   78         File::FileOpenFlags flags = (preserveTimestamps ? File::PreserveTimestamps : File::FlagsNone);
   79 
   80         try
   81         {
   82             if (protection == VolumeProtection::ReadOnly)
   83                 file->Open (volumePath, File::OpenRead, File::ShareRead, flags);
   84             else
   85                 file->Open (volumePath, File::OpenReadWrite, File::ShareNone, flags);
   86         }
   87         catch (SystemException &e)
   88         {
   89             if (e.GetErrorCode() ==
   90 #ifdef TC_WINDOWS
   91                 ERROR_SHARING_VIOLATION)
   92 #else
   93                 EAGAIN)
   94 #endif
   95             {
   96                 if (!sharedAccessAllowed)
   97                     throw VolumeHostInUse (SRC_POS);
   98 
   99                 file->Open (volumePath, protection == VolumeProtection::ReadOnly ? File::OpenRead : File::OpenReadWrite, File::ShareReadWriteIgnoreLock, flags);
  100             }
  101             else
  102                 throw;
  103         }
  104 
  105         return Open (file, password, pim, kdf, truecryptMode, keyfiles, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope);
  106     }
  107 
  108     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)
  109     {
  110         if (!volumeFile)
  111             throw ParameterIncorrect (SRC_POS);
  112 
  113         // TrueCrypt doesn't support SHA-256 and Streebog
  114         if (kdf && truecryptMode && (kdf->GetName() == L"HMAC-SHA-256" || kdf->GetName() == L"HMAC-Streebog"))
  115             throw UnsupportedAlgoInTrueCryptMode (SRC_POS);
  116 
  117         Protection = protection;
  118         VolumeFile = volumeFile;
  119         SystemEncryption = partitionInSystemEncryptionScope;
  120 
  121         try
  122         {
  123             VolumeHostSize = VolumeFile->Length();
  124             shared_ptr <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (keyfiles, password);
  125 
  126             bool skipLayoutV1Normal = false;
  127 
  128             // Test volume layouts
  129             foreach (shared_ptr <VolumeLayout> layout, VolumeLayout::GetAvailableLayouts (volumeType))
  130             {
  131                 if (skipLayoutV1Normal && typeid (*layout) == typeid (VolumeLayoutV1Normal))
  132                 {
  133                     // Skip VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal
  134                     continue;
  135                 }
  136 
  137                 if (useBackupHeaders && !layout->HasBackupHeader())
  138                     continue;
  139 
  140                 SecureBuffer headerBuffer (layout->GetHeaderSize());
  141 
  142                 if (layout->HasDriveHeader())
  143                 {
  144                     if (!partitionInSystemEncryptionScope)
  145                         continue;
  146 
  147                     if (!GetPath().IsDevice())
  148                         throw PartitionDeviceRequired (SRC_POS);
  149 
  150                     File driveDevice;
  151                     driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition());
  152 
  153                     int headerOffset = layout->GetHeaderOffset();
  154 
  155                     if (headerOffset >= 0)
  156                         driveDevice.SeekAt (headerOffset);
  157                     else
  158                         driveDevice.SeekEnd (headerOffset);
  159 
  160                     if (driveDevice.Read (headerBuffer) != layout->GetHeaderSize())
  161                         continue;
  162                 }
  163                 else
  164                 {
  165                     if (partitionInSystemEncryptionScope)
  166                         continue;
  167 
  168                     int headerOffset = useBackupHeaders ? layout->GetBackupHeaderOffset() : layout->GetHeaderOffset();
  169 
  170                     if (headerOffset >= 0)
  171                         VolumeFile->SeekAt (headerOffset);
  172                     else
  173                         VolumeFile->SeekEnd (headerOffset);
  174 
  175                     if (VolumeFile->Read (headerBuffer) != layout->GetHeaderSize())
  176                         continue;
  177                 }
  178 
  179                 EncryptionAlgorithmList layoutEncryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms();
  180                 EncryptionModeList layoutEncryptionModes = layout->GetSupportedEncryptionModes();
  181 
  182                 if (typeid (*layout) == typeid (VolumeLayoutV2Normal))
  183                 {
  184                     skipLayoutV1Normal = true;
  185 
  186                     // Test all algorithms and modes of VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal
  187                     layoutEncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms();
  188                     layoutEncryptionModes = EncryptionMode::GetAvailableModes();
  189                 }
  190 
  191                 shared_ptr <VolumeHeader> header = layout->GetHeader();
  192 
  193                 if (header->Decrypt (headerBuffer, *passwordKey, pim, kdf, truecryptMode, layout->GetSupportedKeyDerivationFunctions(truecryptMode), layoutEncryptionAlgorithms, layoutEncryptionModes))
  194                 {
  195                     // Header decrypted
  196 
  197                     if (!truecryptMode && typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x10b)
  198                     {
  199                         // VolumeLayoutV1Normal has been opened as VolumeLayoutV2Normal
  200                         layout.reset (new VolumeLayoutV1Normal);
  201                         header->SetSize (layout->GetHeaderSize());
  202                         layout->SetHeader (header);
  203                     }
  204 
  205                     TrueCryptMode = truecryptMode;
  206                     Pim = pim;
  207                     Type = layout->GetType();
  208                     SectorSize = header->GetSectorSize();
  209 
  210                     VolumeDataOffset = layout->GetDataOffset (VolumeHostSize);
  211                     VolumeDataSize = layout->GetDataSize (VolumeHostSize);
  212                     EncryptedDataSize = header->GetEncryptedAreaLength();
  213 
  214                     Header = header;
  215                     Layout = layout;
  216                     EA = header->GetEncryptionAlgorithm();
  217                     EncryptionMode &mode = *EA->GetMode();
  218 
  219                     if (layout->HasDriveHeader())
  220                     {
  221                         if (header->GetEncryptedAreaLength() != header->GetVolumeDataSize())
  222                         {
  223                             EncryptionNotCompleted = true;
  224                             // we avoid writing data to the partition since it is only partially encrypted
  225                             Protection = VolumeProtection::ReadOnly;
  226                         }
  227 
  228                         uint64 partitionStartOffset = VolumeFile->GetPartitionDeviceStartOffset();
  229 
  230                         if (partitionStartOffset < header->GetEncryptedAreaStart()
  231                             || partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength())
  232                             throw PasswordIncorrect (SRC_POS);
  233 
  234                         EncryptedDataSize -= partitionStartOffset - header->GetEncryptedAreaStart();
  235 
  236                         mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE);
  237                     }
  238 
  239                     // Volume protection
  240                     if (Protection == VolumeProtection::HiddenVolumeReadOnly)
  241                     {
  242                         if (Type == VolumeType::Hidden)
  243                             throw PasswordIncorrect (SRC_POS);
  244                         else
  245                         {
  246                             try
  247                             {
  248                                 Volume protectedVolume;
  249 
  250                                 protectedVolume.Open (VolumeFile,
  251                                     protectionPassword, protectionPim, protectionKdf, truecryptMode, protectionKeyfiles,
  252                                     VolumeProtection::ReadOnly,
  253                                     shared_ptr <VolumePassword> (), 0, shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> (),
  254                                     VolumeType::Hidden,
  255                                     useBackupHeaders);
  256 
  257                                 if (protectedVolume.GetType() != VolumeType::Hidden)
  258                                     ParameterIncorrect (SRC_POS);
  259 
  260                                 ProtectedRangeStart = protectedVolume.VolumeDataOffset;
  261                                 ProtectedRangeEnd = protectedVolume.VolumeDataOffset + protectedVolume.VolumeDataSize;
  262                             }
  263                             catch (PasswordException&)
  264                             {
  265                                 if (protectionKeyfiles && !protectionKeyfiles->empty())
  266                                     throw ProtectionPasswordKeyfilesIncorrect (SRC_POS);
  267                                 throw ProtectionPasswordIncorrect (SRC_POS);
  268                             }
  269                         }
  270                     }
  271                     return;
  272                 }
  273             }
  274 
  275             if (partitionInSystemEncryptionScope)
  276                 throw PasswordOrKeyboardLayoutIncorrect (SRC_POS);
  277 
  278             if (!partitionInSystemEncryptionScope && GetPath().IsDevice())
  279             {
  280                 // Check if the device contains VeraCrypt Boot Loader
  281                 try
  282                 {
  283                     File driveDevice;
  284                     driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition());
  285 
  286                     Buffer mbr (VolumeFile->GetDeviceSectorSize());
  287                     driveDevice.ReadAt (mbr, 0);
  288 
  289                     // Search for the string "VeraCrypt" or "TrueCrypt"
  290                     const char* bootSignature = truecryptMode? "TrueCrypt" : TC_APP_NAME;
  291                     size_t nameLen = strlen (bootSignature);
  292                     for (size_t i = 0; i < mbr.Size() - nameLen; ++i)
  293                     {
  294                         if (memcmp (mbr.Ptr() + i, bootSignature, nameLen) == 0)
  295                             throw PasswordOrMountOptionsIncorrect (SRC_POS);
  296                     }
  297                 }
  298                 catch (PasswordOrMountOptionsIncorrect&) { throw; }
  299                 catch (...) { }
  300             }
  301 
  302             if (keyfiles && !keyfiles->empty())
  303                 throw PasswordKeyfilesIncorrect (SRC_POS);
  304             throw PasswordIncorrect (SRC_POS);
  305         }
  306         catch (...)
  307         {
  308             Close();
  309             throw;
  310         }
  311     }
  312 
  313     void Volume::ReadSectors (const BufferPtr &buffer, uint64 byteOffset)
  314     {
  315         if_debug (ValidateState ());
  316 
  317         uint64 length = buffer.Size();
  318         uint64 hostOffset = VolumeDataOffset + byteOffset;
  319         size_t bufferOffset = 0;
  320 
  321         if (length % SectorSize != 0 || byteOffset % SectorSize != 0)
  322             throw ParameterIncorrect (SRC_POS);
  323 
  324         if (VolumeFile->ReadAt (buffer, hostOffset) != length)
  325             throw MissingVolumeData (SRC_POS);
  326 
  327         // first sector can be unencrypted in some cases (e.g. windows repair)
  328         // detect this case by looking for NTFS header
  329         if (SystemEncryption && (hostOffset == 0) && ((BE64 (*(uint64 *) buffer.Get ())) == 0xEB52904E54465320ULL))
  330         {
  331             bufferOffset = (size_t) SectorSize;
  332             hostOffset += SectorSize;
  333             length -= SectorSize;
  334         }
  335 
  336         if (length)
  337         {
  338             if (EncryptionNotCompleted)
  339             {
  340                 // if encryption is not complete, we decrypt only the encrypted sectors
  341                 if (hostOffset < EncryptedDataSize)
  342                 {
  343                     uint64 encryptedLength = VC_MIN (length, (EncryptedDataSize - hostOffset));
  344 
  345                     EA->DecryptSectors (buffer.GetRange (bufferOffset, encryptedLength), hostOffset / SectorSize, encryptedLength / SectorSize, SectorSize);            
  346                 }
  347             }
  348             else
  349                 EA->DecryptSectors (buffer.GetRange (bufferOffset, length), hostOffset / SectorSize, length / SectorSize, SectorSize);
  350         }
  351 
  352         TotalDataRead += length;
  353     }
  354 
  355     void Volume::ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf)
  356     {
  357         if_debug (ValidateState ());
  358 
  359         if (Protection == VolumeProtection::ReadOnly)
  360             throw VolumeReadOnly (SRC_POS);
  361 
  362         SecureBuffer newHeaderBuffer (Layout->GetHeaderSize());
  363 
  364         Header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, newPkcs5Kdf);
  365 
  366         int headerOffset = backupHeader ? Layout->GetBackupHeaderOffset() : Layout->GetHeaderOffset();
  367 
  368         if (headerOffset >= 0)
  369             VolumeFile->SeekAt (headerOffset);
  370         else
  371             VolumeFile->SeekEnd (headerOffset);
  372 
  373         VolumeFile->Write (newHeaderBuffer);
  374     }
  375 
  376     void Volume::ValidateState () const
  377     {
  378         if (VolumeFile.get() == nullptr)
  379             throw NotInitialized (SRC_POS);
  380     }
  381 
  382     void Volume::WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset)
  383     {
  384         if_debug (ValidateState ());
  385 
  386         uint64 length = buffer.Size();
  387         uint64 hostOffset = VolumeDataOffset + byteOffset;
  388 
  389         if (length % SectorSize != 0
  390             || byteOffset % SectorSize != 0
  391             || byteOffset + length > VolumeDataSize)
  392             throw ParameterIncorrect (SRC_POS);
  393 
  394         if (Protection == VolumeProtection::ReadOnly)
  395             throw VolumeReadOnly (SRC_POS);
  396 
  397         if (HiddenVolumeProtectionTriggered)
  398             throw VolumeProtected (SRC_POS);
  399 
  400         if (Protection == VolumeProtection::HiddenVolumeReadOnly)
  401             CheckProtectedRange (hostOffset, length);
  402 
  403         SecureBuffer encBuf (buffer.Size());
  404         encBuf.CopyFrom (buffer);
  405 
  406         EA->EncryptSectors (encBuf, hostOffset / SectorSize, length / SectorSize, SectorSize);
  407         VolumeFile->WriteAt (encBuf, hostOffset);
  408 
  409         TotalDataWritten += length;
  410 
  411         uint64 writeEndOffset = byteOffset + buffer.Size();
  412         if (writeEndOffset > TopWriteOffset)
  413             TopWriteOffset = writeEndOffset;
  414     }
  415 }