"Fossies" - the Fresh Open Source Software Archive

Member "src/Core/VolumeCreator.cpp" (10 Oct 2018, 11912 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 "VolumeCreator.cpp" see the Fossies "Dox" file reference documentation.

    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 #include "Volume/EncryptionTest.h"
   14 #include "Volume/EncryptionModeXTS.h"
   15 #include "Core.h"
   16 
   17 #ifdef TC_UNIX
   18 #include <sys/types.h>
   19 #include <sys/stat.h>
   20 #include <unistd.h>
   21 #endif
   22 
   23 #include "VolumeCreator.h"
   24 #include "FatFormatter.h"
   25 
   26 namespace VeraCrypt
   27 {
   28     VolumeCreator::VolumeCreator ()
   29         : SizeDone (0)
   30     {
   31     }
   32 
   33     VolumeCreator::~VolumeCreator ()
   34     {
   35     }
   36 
   37     void VolumeCreator::Abort ()
   38     {
   39         AbortRequested = true;
   40     }
   41 
   42     void VolumeCreator::CheckResult ()
   43     {
   44         if (ThreadException)
   45             ThreadException->Throw();
   46     }
   47 
   48     void VolumeCreator::CreationThread ()
   49     {
   50         try
   51         {
   52             uint64 endOffset;
   53             uint64 filesystemSize = Layout->GetDataSize (HostSize);
   54 
   55             if (filesystemSize < 1)
   56                 throw ParameterIncorrect (SRC_POS);
   57 
   58             DataStart = Layout->GetDataOffset (HostSize);
   59             WriteOffset = DataStart;
   60             endOffset = DataStart + Layout->GetDataSize (HostSize);
   61 
   62             VolumeFile->SeekAt (DataStart);
   63 
   64             // Create filesystem
   65             if (Options->Filesystem == VolumeCreationOptions::FilesystemType::FAT)
   66             {
   67                 if (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_SECTOR_COUNT * Options->SectorSize)
   68                     throw ParameterIncorrect (SRC_POS);
   69 
   70                 struct WriteSectorCallback : public FatFormatter::WriteSectorCallback
   71                 {
   72                     WriteSectorCallback (VolumeCreator *creator) : Creator (creator), OutputBuffer (File::GetOptimalWriteSize()), OutputBufferWritePos (0) { }
   73 
   74                     virtual bool operator() (const BufferPtr &sector)
   75                     {
   76                         OutputBuffer.GetRange (OutputBufferWritePos, sector.Size()).CopyFrom (sector);
   77                         OutputBufferWritePos += sector.Size();
   78 
   79                         if (OutputBufferWritePos >= OutputBuffer.Size())
   80                             FlushOutputBuffer();
   81 
   82                         return !Creator->AbortRequested;
   83                     }
   84 
   85                     void FlushOutputBuffer ()
   86                     {
   87                         if (OutputBufferWritePos > 0)
   88                         {
   89                             Creator->Options->EA->EncryptSectors (OutputBuffer.GetRange (0, OutputBufferWritePos),
   90                                 Creator->WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, OutputBufferWritePos / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
   91 
   92                             Creator->VolumeFile->Write (OutputBuffer.GetRange (0, OutputBufferWritePos));
   93 
   94                             Creator->WriteOffset += OutputBufferWritePos;
   95                             Creator->SizeDone.Set (Creator->WriteOffset - Creator->DataStart);
   96 
   97                             OutputBufferWritePos = 0;
   98                         }
   99                     }
  100 
  101                     VolumeCreator *Creator;
  102                     SecureBuffer OutputBuffer;
  103                     size_t OutputBufferWritePos;
  104                 };
  105 
  106                 WriteSectorCallback sectorWriter (this);
  107                 FatFormatter::Format (sectorWriter, filesystemSize, Options->FilesystemClusterSize, Options->SectorSize);
  108                 sectorWriter.FlushOutputBuffer();
  109             }
  110 
  111             if (!Options->Quick)
  112             {
  113                 // Empty sectors are encrypted with different key to randomize plaintext
  114                 Core->RandomizeEncryptionAlgorithmKey (Options->EA);
  115 
  116                 SecureBuffer outputBuffer (File::GetOptimalWriteSize());
  117                 uint64 dataFragmentLength = outputBuffer.Size();
  118 
  119                 while (!AbortRequested && WriteOffset < endOffset)
  120                 {
  121                     if (WriteOffset + dataFragmentLength > endOffset)
  122                         dataFragmentLength = endOffset - WriteOffset;
  123 
  124                     outputBuffer.Zero();
  125                     Options->EA->EncryptSectors (outputBuffer, WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, dataFragmentLength / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
  126                     VolumeFile->Write (outputBuffer, (size_t) dataFragmentLength);
  127 
  128                     WriteOffset += dataFragmentLength;
  129                     SizeDone.Set (WriteOffset - DataStart);
  130                 }
  131             }
  132 
  133             if (!AbortRequested)
  134             {
  135                 SizeDone.Set (Options->Size);
  136 
  137                 // Backup header
  138                 SecureBuffer backupHeader (Layout->GetHeaderSize());
  139 
  140                 SecureBuffer backupHeaderSalt (VolumeHeader::GetSaltSize());
  141                 RandomNumberGenerator::GetData (backupHeaderSalt);
  142 
  143                 Options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, Options->Pim, backupHeaderSalt);
  144 
  145                 Layout->GetHeader()->EncryptNew (backupHeader, backupHeaderSalt, HeaderKey, Options->VolumeHeaderKdf);
  146 
  147                 if (Options->Quick || Options->Type == VolumeType::Hidden)
  148                     VolumeFile->SeekEnd (Layout->GetBackupHeaderOffset());
  149 
  150                 VolumeFile->Write (backupHeader);
  151 
  152                 if (Options->Type == VolumeType::Normal)
  153                 {
  154                     // Write fake random header to space reserved for hidden volume header
  155                     VolumeLayoutV2Hidden hiddenLayout;
  156                     shared_ptr <VolumeHeader> hiddenHeader (hiddenLayout.GetHeader());
  157                     SecureBuffer hiddenHeaderBuffer (hiddenLayout.GetHeaderSize());
  158 
  159                     VolumeHeaderCreationOptions headerOptions;
  160                     headerOptions.EA = Options->EA;
  161                     headerOptions.Kdf = Options->VolumeHeaderKdf;
  162                     headerOptions.Type = VolumeType::Hidden;
  163 
  164                     headerOptions.SectorSize = Options->SectorSize;
  165 
  166                     headerOptions.VolumeDataStart = HostSize - hiddenLayout.GetHeaderSize() * 2 - Options->Size;
  167                     headerOptions.VolumeDataSize = hiddenLayout.GetMaxDataSize (Options->Size);
  168 
  169                     // Master data key
  170                     SecureBuffer hiddenMasterKey(Options->EA->GetKeySize() * 2);
  171                     RandomNumberGenerator::GetData (hiddenMasterKey);
  172                     headerOptions.DataKey = hiddenMasterKey;
  173 
  174                     // PKCS5 salt
  175                     SecureBuffer hiddenSalt (VolumeHeader::GetSaltSize());
  176                     RandomNumberGenerator::GetData (hiddenSalt);
  177                     headerOptions.Salt = hiddenSalt;
  178 
  179                     // Header key
  180                     SecureBuffer hiddenHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
  181                     RandomNumberGenerator::GetData (hiddenHeaderKey);
  182                     headerOptions.HeaderKey = hiddenHeaderKey;
  183 
  184                     hiddenHeader->Create (backupHeader, headerOptions);
  185 
  186                     VolumeFile->Write (backupHeader);
  187                 }
  188 
  189                 VolumeFile->Flush();
  190             }
  191         }
  192         catch (Exception &e)
  193         {
  194             ThreadException.reset (e.CloneNew());
  195         }
  196         catch (exception &e)
  197         {
  198             ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
  199         }
  200         catch (...)
  201         {
  202             ThreadException.reset (new UnknownException (SRC_POS));
  203         }
  204 
  205         VolumeFile.reset();
  206         mProgressInfo.CreationInProgress = false;
  207     }
  208 
  209     void VolumeCreator::CreateVolume (shared_ptr <VolumeCreationOptions> options)
  210     {
  211         EncryptionTest::TestAll();
  212 
  213         {
  214 #ifdef TC_UNIX
  215             // Temporarily take ownership of a device if the user is not an administrator
  216             UserId origDeviceOwner ((uid_t) -1);
  217 
  218             if (!Core->HasAdminPrivileges() && options->Path.IsDevice())
  219             {
  220                 origDeviceOwner = FilesystemPath (wstring (options->Path)).GetOwner();
  221                 Core->SetFileOwner (options->Path, UserId (getuid()));
  222             }
  223 
  224             finally_do_arg2 (FilesystemPath, options->Path, UserId, origDeviceOwner,
  225             {
  226                 if (finally_arg2.SystemId != (uid_t) -1)
  227                     Core->SetFileOwner (finally_arg, finally_arg2);
  228             });
  229 #endif
  230 
  231             VolumeFile.reset (new File);
  232             VolumeFile->Open (options->Path,
  233                 (options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite,
  234                 File::ShareNone);
  235 
  236             HostSize = VolumeFile->Length();
  237         }
  238 
  239         try
  240         {
  241             // Sector size
  242             if (options->Path.IsDevice())
  243             {
  244                 options->SectorSize = VolumeFile->GetDeviceSectorSize();
  245 
  246                 if (options->SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
  247                     || options->SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
  248 #if !defined (TC_LINUX) && !defined (TC_MACOSX)
  249                     || options->SectorSize != TC_SECTOR_SIZE_LEGACY
  250 #endif
  251                     || options->SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
  252                 {
  253                     throw UnsupportedSectorSize (SRC_POS);
  254                 }
  255             }
  256             else
  257                 options->SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
  258 
  259             // Volume layout
  260             switch (options->Type)
  261             {
  262             case VolumeType::Normal:
  263                 Layout.reset (new VolumeLayoutV2Normal());
  264                 break;
  265 
  266             case VolumeType::Hidden:
  267                 Layout.reset (new VolumeLayoutV2Hidden());
  268 
  269                 if (HostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE)
  270                     throw ParameterIncorrect (SRC_POS);
  271                 break;
  272 
  273             default:
  274                 throw ParameterIncorrect (SRC_POS);
  275             }
  276 
  277             // Volume header
  278             shared_ptr <VolumeHeader> header (Layout->GetHeader());
  279             SecureBuffer headerBuffer (Layout->GetHeaderSize());
  280 
  281             VolumeHeaderCreationOptions headerOptions;
  282             headerOptions.EA = options->EA;
  283             headerOptions.Kdf = options->VolumeHeaderKdf;
  284             headerOptions.Type = options->Type;
  285 
  286             headerOptions.SectorSize = options->SectorSize;
  287 
  288             if (options->Type == VolumeType::Hidden)
  289                 headerOptions.VolumeDataStart = HostSize - Layout->GetHeaderSize() * 2 - options->Size;
  290             else
  291                 headerOptions.VolumeDataStart = Layout->GetHeaderSize() * 2;
  292 
  293             headerOptions.VolumeDataSize = Layout->GetMaxDataSize (options->Size);
  294 
  295             if (headerOptions.VolumeDataSize < 1)
  296                 throw ParameterIncorrect (SRC_POS);
  297 
  298             // Master data key
  299             MasterKey.Allocate (options->EA->GetKeySize() * 2);
  300             RandomNumberGenerator::GetData (MasterKey);
  301             headerOptions.DataKey = MasterKey;
  302 
  303             // PKCS5 salt
  304             SecureBuffer salt (VolumeHeader::GetSaltSize());
  305             RandomNumberGenerator::GetData (salt);
  306             headerOptions.Salt = salt;
  307 
  308             // Header key
  309             HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize());
  310             PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password);
  311             options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt);
  312             headerOptions.HeaderKey = HeaderKey;
  313 
  314             header->Create (headerBuffer, headerOptions);
  315 
  316             // Write new header
  317             if (Layout->GetHeaderOffset() >= 0)
  318                 VolumeFile->SeekAt (Layout->GetHeaderOffset());
  319             else
  320                 VolumeFile->SeekEnd (Layout->GetHeaderOffset());
  321 
  322             VolumeFile->Write (headerBuffer);
  323 
  324             if (options->Type == VolumeType::Normal)
  325             {
  326                 // Write fake random header to space reserved for hidden volume header
  327                 VolumeLayoutV2Hidden hiddenLayout;
  328                 shared_ptr <VolumeHeader> hiddenHeader (hiddenLayout.GetHeader());
  329                 SecureBuffer hiddenHeaderBuffer (hiddenLayout.GetHeaderSize());
  330 
  331                 headerOptions.Type = VolumeType::Hidden;
  332 
  333                 headerOptions.VolumeDataStart = HostSize - hiddenLayout.GetHeaderSize() * 2 - options->Size;
  334                 headerOptions.VolumeDataSize = hiddenLayout.GetMaxDataSize (options->Size);
  335 
  336                 // Master data key
  337                 SecureBuffer hiddenMasterKey(options->EA->GetKeySize() * 2);
  338                 RandomNumberGenerator::GetData (hiddenMasterKey);
  339                 headerOptions.DataKey = hiddenMasterKey;
  340 
  341                 // PKCS5 salt
  342                 SecureBuffer hiddenSalt (VolumeHeader::GetSaltSize());
  343                 RandomNumberGenerator::GetData (hiddenSalt);
  344                 headerOptions.Salt = hiddenSalt;
  345 
  346                 // Header key
  347                 SecureBuffer hiddenHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
  348                 RandomNumberGenerator::GetData (hiddenHeaderKey);
  349                 headerOptions.HeaderKey = hiddenHeaderKey;
  350 
  351                 hiddenHeader->Create (headerBuffer, headerOptions);
  352 
  353                 VolumeFile->Write (headerBuffer);
  354             }
  355 
  356             // Data area keys
  357             options->EA->SetKey (MasterKey.GetRange (0, options->EA->GetKeySize()));
  358             shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ());
  359             mode->SetKey (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize()));
  360             options->EA->SetMode (mode);
  361 
  362             Options = options;
  363             AbortRequested = false;
  364 
  365             mProgressInfo.CreationInProgress = true;
  366 
  367             struct ThreadFunctor : public Functor
  368             {
  369                 ThreadFunctor (VolumeCreator *creator) : Creator (creator) { }
  370                 virtual void operator() ()
  371                 {
  372                     Creator->CreationThread ();
  373                 }
  374                 VolumeCreator *Creator;
  375             };
  376 
  377             Thread thread;
  378             thread.Start (new ThreadFunctor (this));
  379         }
  380         catch (...)
  381         {
  382             VolumeFile.reset();
  383             throw;
  384         }
  385     }
  386 
  387     VolumeCreator::KeyInfo VolumeCreator::GetKeyInfo () const
  388     {
  389         KeyInfo info;
  390         info.HeaderKey = HeaderKey;
  391         info.MasterKey = MasterKey;
  392         return info;
  393     }
  394 
  395     VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo ()
  396     {
  397         mProgressInfo.SizeDone = SizeDone.Get();
  398         return mProgressInfo;
  399     }
  400 }