"Fossies" - the Fresh Open Source Software Archive

Member "src/Core/CoreBase.cpp" (10 Oct 2018, 9720 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 "CoreBase.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 <set>
   14 
   15 #include "CoreBase.h"
   16 #include "RandomNumberGenerator.h"
   17 #include "Volume/Volume.h"
   18 
   19 namespace VeraCrypt
   20 {
   21     CoreBase::CoreBase ()
   22         : DeviceChangeInProgress (false)
   23     {
   24     }
   25 
   26     CoreBase::~CoreBase ()
   27     {
   28     }
   29 
   30     void CoreBase::ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf, int wipeCount) const
   31     {
   32         if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty()))
   33             throw PasswordEmpty (SRC_POS);
   34 
   35         if (!newPkcs5Kdf)
   36         {
   37             if (openVolume->GetPkcs5Kdf()->GetTrueCryptMode ())
   38             {
   39                 newPkcs5Kdf.reset (openVolume->GetPkcs5Kdf()->Clone());
   40                 newPkcs5Kdf->SetTrueCryptMode (false);
   41             }
   42             else
   43                 newPkcs5Kdf = openVolume->GetPkcs5Kdf();
   44         }
   45 
   46         if ((openVolume->GetHeader()->GetFlags() & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) != 0
   47             && openVolume->GetType() == VolumeType::Hidden
   48             && openVolume->GetPath().IsDevice())
   49         {
   50             throw EncryptedSystemRequired (SRC_POS);
   51         }
   52 
   53         RandomNumberGenerator::SetHash (newPkcs5Kdf->GetHash());
   54 
   55         SecureBuffer newSalt (openVolume->GetSaltSize());
   56         SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
   57 
   58         shared_ptr <VolumePassword> password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword));
   59 
   60         bool backupHeader = false;
   61         while (true)
   62         {
   63             for (int i = 1; i <= wipeCount; i++)
   64             {
   65                 if (i == wipeCount)
   66                     RandomNumberGenerator::GetData (newSalt);
   67                 else
   68                     RandomNumberGenerator::GetDataFast (newSalt);
   69 
   70                 newPkcs5Kdf->DeriveKey (newHeaderKey, *password, newPim, newSalt);
   71 
   72                 openVolume->ReEncryptHeader (backupHeader, newSalt, newHeaderKey, newPkcs5Kdf);
   73                 openVolume->GetFile()->Flush();
   74             }
   75 
   76             if (!openVolume->GetLayout()->HasBackupHeader() || backupHeader)
   77                 break;
   78 
   79             backupHeader = true;
   80         }
   81     }
   82 
   83     void CoreBase::ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf, int wipeCount) const
   84     {
   85         shared_ptr <Volume> volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles);
   86         ChangePassword (volume, newPassword, newPim, newKeyfiles, newPkcs5Kdf, wipeCount);
   87     }
   88 
   89     void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const
   90     {
   91         if (options.SlotNumber < GetFirstSlotNumber())
   92         {
   93             if (options.MountPoint && !options.MountPoint->IsEmpty())
   94                 options.SlotNumber = MountPointToSlotNumber (*options.MountPoint);
   95             else
   96                 options.SlotNumber = GetFirstFreeSlotNumber();
   97         }
   98 
   99         if (!IsSlotNumberAvailable (options.SlotNumber))
  100 #ifdef TC_WINDOWS
  101             throw DriveLetterUnavailable (SRC_POS);
  102 #else
  103             throw VolumeSlotUnavailable (SRC_POS);
  104 #endif
  105         if (!options.NoFilesystem && (!options.MountPoint || options.MountPoint->IsEmpty()))
  106             options.MountPoint.reset (new DirectoryPath (SlotNumberToMountPoint (options.SlotNumber)));
  107     }
  108 
  109     void CoreBase::CreateKeyfile (const FilePath &keyfilePath) const
  110     {
  111         SecureBuffer keyfileBuffer (VolumePassword::MaxSize);
  112         RandomNumberGenerator::GetData (keyfileBuffer);
  113 
  114         File keyfile;
  115         keyfile.Open (keyfilePath, File::CreateWrite);
  116         keyfile.Write (keyfileBuffer);
  117     }
  118 
  119     VolumeSlotNumber CoreBase::GetFirstFreeSlotNumber (VolumeSlotNumber startFrom) const
  120     {
  121         if (startFrom < GetFirstSlotNumber())
  122             startFrom = GetFirstSlotNumber();
  123 
  124         set <VolumeSlotNumber> usedSlotNumbers;
  125 
  126         foreach_ref (const VolumeInfo &volume, GetMountedVolumes())
  127             usedSlotNumbers.insert (volume.SlotNumber);
  128 
  129         for (VolumeSlotNumber slotNumber = startFrom; slotNumber <= GetLastSlotNumber(); ++slotNumber)
  130         {
  131             if (usedSlotNumbers.find (slotNumber) == usedSlotNumbers.end()
  132                 && IsMountPointAvailable (SlotNumberToMountPoint (slotNumber)))
  133                 return slotNumber;
  134         }
  135 #ifdef TC_WINDOWS
  136         throw DriveLetterUnavailable (SRC_POS);
  137 #else
  138         throw VolumeSlotUnavailable (SRC_POS);
  139 #endif
  140     }
  141 
  142     uint64 CoreBase::GetMaxHiddenVolumeSize (shared_ptr <Volume> outerVolume) const
  143     {
  144         uint32 sectorSize = outerVolume->GetSectorSize();
  145 
  146         SecureBuffer bootSectorBuffer (sectorSize);
  147         outerVolume->ReadSectors (bootSectorBuffer, 0);
  148 
  149         int fatType;
  150         byte *bootSector = bootSectorBuffer.Ptr();
  151 
  152         if (memcmp (bootSector + 54, "FAT12", 5) == 0)
  153             fatType = 12;
  154         else if (memcmp (bootSector + 54, "FAT16", 5) == 0)
  155             fatType = 16;
  156         else if (memcmp (bootSector + 82, "FAT32", 5) == 0)
  157             fatType = 32;
  158         else
  159             throw ParameterIncorrect (SRC_POS);
  160 
  161         uint32 clusterSize = bootSector[13] * sectorSize;
  162         uint32 reservedSectorCount = Endian::Little (*(uint16 *) (bootSector + 14));
  163         uint32 fatCount = bootSector[16];
  164 
  165         uint64 fatSectorCount;
  166         if (fatType == 32)
  167             fatSectorCount = Endian::Little (*(uint32 *) (bootSector + 36));
  168         else
  169             fatSectorCount = Endian::Little (*(uint16 *) (bootSector + 22));
  170         uint64 fatSize = fatSectorCount * sectorSize;
  171 
  172         uint64 fatStartOffset = reservedSectorCount * sectorSize;
  173         uint64 dataAreaOffset = reservedSectorCount * sectorSize + fatSize * fatCount;
  174 
  175         if (fatType < 32)
  176             dataAreaOffset += Endian::Little (*(uint16 *) (bootSector + 17)) * 32;
  177 
  178         SecureBuffer sector (sectorSize);
  179 
  180         // Find last used cluster
  181         for (uint64 readOffset = fatStartOffset + fatSize - sectorSize;
  182             readOffset >= fatStartOffset;
  183             readOffset -= sectorSize)
  184         {
  185             outerVolume->ReadSectors (sector, readOffset);
  186 
  187             for (int offset = sectorSize - 4; offset >= 0; offset -= 4)
  188             {
  189                 if (*(uint32 *) (sector.Ptr() + offset))
  190                 {
  191                     uint64 clusterNumber = readOffset - fatStartOffset + offset;
  192 
  193                     if (fatType == 12)
  194                         clusterNumber = (clusterNumber * 8) / 12;
  195                     else if (fatType == 16)
  196                         clusterNumber /= 2;
  197                     else if (fatType == 32)
  198                         clusterNumber /= 4;
  199 
  200                     uint64 maxSize = outerVolume->GetSize() - dataAreaOffset;
  201 
  202                     // Some FAT entries may span over sector boundaries
  203                     if (maxSize >= clusterSize)
  204                         maxSize -= clusterSize;
  205 
  206                     uint64 clusterOffset = clusterNumber * clusterSize;
  207                     if (maxSize < clusterOffset)
  208                         return 0;
  209 
  210                     return maxSize - clusterOffset;
  211                 }
  212             }
  213         }
  214 
  215         return 0;
  216     }
  217 
  218     shared_ptr <VolumeInfo> CoreBase::GetMountedVolume (const VolumePath &volumePath) const
  219     {
  220         VolumeInfoList volumes = GetMountedVolumes (volumePath);
  221         if (volumes.empty())
  222             return shared_ptr <VolumeInfo> ();
  223         else
  224             return volumes.front();
  225     }
  226 
  227     shared_ptr <VolumeInfo> CoreBase::GetMountedVolume (VolumeSlotNumber slot) const
  228     {
  229         foreach (shared_ptr <VolumeInfo> volume, GetMountedVolumes())
  230         {
  231             if (volume->SlotNumber == slot)
  232                 return volume;
  233         }
  234 
  235         return shared_ptr <VolumeInfo> ();
  236     }
  237 
  238     bool CoreBase::IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const
  239     {
  240         if (!IsMountPointAvailable (SlotNumberToMountPoint (slotNumber)))
  241             return false;
  242 
  243         foreach_ref (const VolumeInfo &volume, GetMountedVolumes())
  244         {
  245             if (volume.SlotNumber == slotNumber)
  246                 return false;
  247         }
  248 
  249         return true;
  250     }
  251 
  252     bool CoreBase::IsVolumeMounted (const VolumePath &volumePath) const
  253     {
  254         return GetMountedVolume (volumePath);
  255     }
  256 
  257     shared_ptr <Volume> CoreBase::OpenVolume (shared_ptr <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) const
  258     {
  259         make_shared_auto (Volume, volume);
  260         volume->Open (*volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, protection, protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope);
  261         return volume;
  262     }
  263 
  264     void CoreBase::RandomizeEncryptionAlgorithmKey (shared_ptr <EncryptionAlgorithm> encryptionAlgorithm) const
  265     {
  266         SecureBuffer eaKey (encryptionAlgorithm->GetKeySize());
  267         RandomNumberGenerator::GetData (eaKey);
  268         encryptionAlgorithm->SetKey (eaKey);
  269 
  270         SecureBuffer modeKey (encryptionAlgorithm->GetMode()->GetKeySize());
  271         RandomNumberGenerator::GetData (modeKey);
  272         encryptionAlgorithm->GetMode()->SetKey (modeKey);
  273     }
  274 
  275     void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> keyfiles) const
  276     {
  277         shared_ptr <Pkcs5Kdf> pkcs5Kdf = header->GetPkcs5Kdf();
  278 
  279         RandomNumberGenerator::SetHash (pkcs5Kdf->GetHash());
  280 
  281         SecureBuffer newSalt (header->GetSaltSize());
  282         SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
  283 
  284         shared_ptr <VolumePassword> passwordKey (Keyfile::ApplyListToPassword (keyfiles, password));
  285 
  286         RandomNumberGenerator::GetData (newSalt);
  287         pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, pim, newSalt);
  288 
  289         header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, pkcs5Kdf);
  290     }
  291 }