"Fossies" - the Fresh Open Source Software Archive

Member "src/Volume/VolumeHeader.cpp" (10 Oct 2018, 11141 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 "VolumeHeader.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 "Crc32.h"
   14 #include "EncryptionModeXTS.h"
   15 #include "Pkcs5Kdf.h"
   16 #include "Pkcs5Kdf.h"
   17 #include "VolumeHeader.h"
   18 #include "VolumeException.h"
   19 #include "Common/Crypto.h"
   20 
   21 namespace VeraCrypt
   22 {
   23     VolumeHeader::VolumeHeader (uint32 size)
   24     {
   25         Init();
   26         HeaderSize = size;
   27         EncryptedHeaderDataSize = size - EncryptedHeaderDataOffset;
   28     }
   29 
   30     VolumeHeader::~VolumeHeader ()
   31     {
   32         Init();
   33     }
   34 
   35     void VolumeHeader::Init ()
   36     {
   37         VolumeKeyAreaCrc32 = 0;
   38         VolumeCreationTime = 0;
   39         HeaderCreationTime = 0;
   40         mVolumeType = VolumeType::Unknown;
   41         HiddenVolumeDataSize = 0;
   42         VolumeDataSize = 0;
   43         EncryptedAreaStart = 0;
   44         EncryptedAreaLength = 0;
   45         Flags = 0;
   46         SectorSize = 0;
   47     }
   48 
   49     void VolumeHeader::Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options)
   50     {
   51         if (options.DataKey.Size() != options.EA->GetKeySize() * 2 || options.Salt.Size() != GetSaltSize())
   52             throw ParameterIncorrect (SRC_POS);
   53 
   54         headerBuffer.Zero();
   55 
   56         HeaderVersion = CurrentHeaderVersion;
   57         RequiredMinProgramVersion = CurrentRequiredMinProgramVersion;
   58 
   59         DataAreaKey.Zero();
   60         DataAreaKey.CopyFrom (options.DataKey);
   61 
   62         VolumeCreationTime = 0;
   63         HiddenVolumeDataSize = (options.Type == VolumeType::Hidden ? options.VolumeDataSize : 0);
   64         VolumeDataSize = options.VolumeDataSize;
   65 
   66         EncryptedAreaStart = options.VolumeDataStart;
   67         EncryptedAreaLength = options.VolumeDataSize;
   68 
   69         SectorSize = options.SectorSize;
   70 
   71         if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
   72             || SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
   73             || SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
   74         {
   75             throw ParameterIncorrect (SRC_POS);
   76         }
   77 
   78         EA = options.EA;
   79         shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ());
   80         EA->SetMode (mode);
   81 
   82         EncryptNew (headerBuffer, options.Salt, options.HeaderKey, options.Kdf);
   83     }
   84 
   85     bool VolumeHeader::Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes)
   86     {
   87         if (password.Size() < 1)
   88             throw PasswordEmpty (SRC_POS);
   89 
   90         ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize));
   91         SecureBuffer header (EncryptedHeaderDataSize);
   92         SecureBuffer headerKey (GetLargestSerializedKeySize());
   93 
   94         foreach (shared_ptr <Pkcs5Kdf> pkcs5, keyDerivationFunctions)
   95         {
   96             if (kdf && (kdf->GetName() != pkcs5->GetName()))
   97                 continue;
   98 
   99             pkcs5->DeriveKey (headerKey, password, pim, salt);
  100 
  101             foreach (shared_ptr <EncryptionMode> mode, encryptionModes)
  102             {
  103                 if (typeid (*mode) != typeid (EncryptionModeXTS))
  104                     mode->SetKey (headerKey.GetRange (0, mode->GetKeySize()));
  105 
  106                 foreach (shared_ptr <EncryptionAlgorithm> ea, encryptionAlgorithms)
  107                 {
  108                     if (!ea->IsModeSupported (mode))
  109                         continue;
  110 
  111                     if (typeid (*mode) == typeid (EncryptionModeXTS))
  112                     {
  113                         ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
  114 
  115                         mode = mode->GetNew();
  116                         mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
  117                     }
  118                     else
  119                     {
  120                         ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
  121                     }
  122 
  123                     ea->SetMode (mode);
  124 
  125                     header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize));
  126                     ea->Decrypt (header);
  127 
  128                     if (Deserialize (header, ea, mode, truecryptMode))
  129                     {
  130                         EA = ea;
  131                         Pkcs5 = pkcs5;
  132                         return true;
  133                     }
  134                 }
  135             }
  136         }
  137 
  138         return false;
  139     }
  140 
  141     bool VolumeHeader::Deserialize (const ConstBufferPtr &header, shared_ptr <EncryptionAlgorithm> &ea, shared_ptr <EncryptionMode> &mode, bool truecryptMode)
  142     {
  143         if (header.Size() != EncryptedHeaderDataSize)
  144             throw ParameterIncorrect (SRC_POS);
  145 
  146         if (truecryptMode && (header[0] != 'T' ||
  147             header[1] != 'R' ||
  148             header[2] != 'U' ||
  149             header[3] != 'E'))
  150             return false;
  151 
  152         if (!truecryptMode && (header[0] != 'V' ||
  153             header[1] != 'E' ||
  154             header[2] != 'R' ||
  155             header[3] != 'A'))
  156             return false;
  157 
  158         size_t offset = 4;
  159         HeaderVersion = DeserializeEntry <uint16> (header, offset);
  160 
  161         if (HeaderVersion < MinAllowedHeaderVersion)
  162             return false;
  163 
  164         if (HeaderVersion > CurrentHeaderVersion)
  165             throw HigherVersionRequired (SRC_POS);
  166 
  167         if (HeaderVersion >= 4
  168             && Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
  169             != DeserializeEntryAt <uint32> (header, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
  170         {
  171             return false;
  172         }
  173 
  174         RequiredMinProgramVersion = DeserializeEntry <uint16> (header, offset);
  175 
  176         if (!truecryptMode && (RequiredMinProgramVersion > Version::Number()))
  177             throw HigherVersionRequired (SRC_POS);
  178 
  179         if (truecryptMode)
  180         {
  181             if (RequiredMinProgramVersion < 0x600 || RequiredMinProgramVersion > 0x71a)
  182                 throw UnsupportedTrueCryptFormat (SRC_POS);
  183             RequiredMinProgramVersion = CurrentRequiredMinProgramVersion;
  184         }
  185 
  186         VolumeKeyAreaCrc32 = DeserializeEntry <uint32> (header, offset);
  187         VolumeCreationTime = DeserializeEntry <uint64> (header, offset);
  188         HeaderCreationTime = DeserializeEntry <uint64> (header, offset);
  189         HiddenVolumeDataSize = DeserializeEntry <uint64> (header, offset);
  190         mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal);
  191         VolumeDataSize = DeserializeEntry <uint64> (header, offset);
  192         EncryptedAreaStart = DeserializeEntry <uint64> (header, offset);
  193         EncryptedAreaLength = DeserializeEntry <uint64> (header, offset);
  194         Flags = DeserializeEntry <uint32> (header, offset);
  195 
  196         SectorSize = DeserializeEntry <uint32> (header, offset);
  197         if (HeaderVersion < 5)
  198             SectorSize = TC_SECTOR_SIZE_LEGACY;
  199 
  200         if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
  201             || SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
  202             || SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
  203         {
  204             throw ParameterIncorrect (SRC_POS);
  205         }
  206 
  207 #if !(defined (TC_WINDOWS) || defined (TC_LINUX) || defined (TC_MACOSX))
  208         if (SectorSize != TC_SECTOR_SIZE_LEGACY)
  209             throw UnsupportedSectorSize (SRC_POS);
  210 #endif
  211 
  212         offset = DataAreaKeyOffset;
  213 
  214         if (VolumeKeyAreaCrc32 != Crc32::ProcessBuffer (header.GetRange (offset, DataKeyAreaMaxSize)))
  215             return false;
  216 
  217         DataAreaKey.CopyFrom (header.GetRange (offset, DataKeyAreaMaxSize));
  218 
  219         ea = ea->GetNew();
  220         mode = mode->GetNew();
  221 
  222         if (typeid (*mode) == typeid (EncryptionModeXTS))
  223         {
  224             ea->SetKey (header.GetRange (offset, ea->GetKeySize()));
  225             mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize()));
  226         }
  227         else
  228         {
  229             mode->SetKey (header.GetRange (offset, mode->GetKeySize()));
  230             ea->SetKey (header.GetRange (offset + LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
  231         }
  232 
  233         ea->SetMode (mode);
  234 
  235         return true;
  236     }
  237 
  238     template <typename T>
  239     T VolumeHeader::DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const
  240     {
  241         offset += sizeof (T);
  242 
  243         if (offset > header.Size())
  244             throw ParameterIncorrect (SRC_POS);
  245 
  246         return Endian::Big (*reinterpret_cast<const T *> (header.Get() + offset - sizeof (T)));
  247     }
  248 
  249     template <typename T>
  250     T VolumeHeader::DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const
  251     {
  252         if (offset > header.Size())
  253             throw ParameterIncorrect (SRC_POS);
  254 
  255         return Endian::Big (*reinterpret_cast<const T *> (header.Get() + offset));
  256     }
  257 
  258     void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf)
  259     {
  260         if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize)
  261             throw ParameterIncorrect (SRC_POS);
  262 
  263         shared_ptr <EncryptionMode> mode = EA->GetMode()->GetNew();
  264         shared_ptr <EncryptionAlgorithm> ea = EA->GetNew();
  265 
  266         if (typeid (*mode) == typeid (EncryptionModeXTS))
  267         {
  268             mode->SetKey (newHeaderKey.GetRange (EA->GetKeySize(), EA->GetKeySize()));
  269             ea->SetKey (newHeaderKey.GetRange (0, ea->GetKeySize()));
  270         }
  271         else
  272         {
  273             mode->SetKey (newHeaderKey.GetRange (0, mode->GetKeySize()));
  274             ea->SetKey (newHeaderKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
  275         }
  276 
  277         ea->SetMode (mode);
  278 
  279         newHeaderBuffer.CopyFrom (newSalt);
  280 
  281         BufferPtr headerData = newHeaderBuffer.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize);
  282         Serialize (headerData);
  283         ea->Encrypt (headerData);
  284 
  285         if (newPkcs5Kdf)
  286             Pkcs5 = newPkcs5Kdf;
  287     }
  288 
  289     size_t VolumeHeader::GetLargestSerializedKeySize ()
  290     {
  291         size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms());
  292 
  293         // XTS mode requires the same key size as the encryption algorithm.
  294         // Legacy modes may require larger key than XTS.
  295         if (LegacyEncryptionModeKeyAreaSize + largestKey > largestKey * 2)
  296             return LegacyEncryptionModeKeyAreaSize + largestKey;
  297 
  298         return largestKey * 2;
  299     }
  300 
  301     void VolumeHeader::Serialize (const BufferPtr &header) const
  302     {
  303         if (header.Size() != EncryptedHeaderDataSize)
  304             throw ParameterIncorrect (SRC_POS);
  305 
  306         header.Zero();
  307 
  308         header[0] = 'V';
  309         header[1] = 'E';
  310         header[2] = 'R';
  311         header[3] = 'A';
  312         size_t offset = 4;
  313 
  314         header.GetRange (DataAreaKeyOffset, DataAreaKey.Size()).CopyFrom (DataAreaKey);
  315 
  316         uint16 headerVersion = CurrentHeaderVersion;
  317         SerializeEntry (headerVersion, header, offset);
  318         SerializeEntry (RequiredMinProgramVersion, header, offset);
  319         SerializeEntry (Crc32::ProcessBuffer (header.GetRange (DataAreaKeyOffset, DataKeyAreaMaxSize)), header, offset);
  320 
  321         uint64 reserved64 = 0;
  322         SerializeEntry (reserved64, header, offset);
  323         SerializeEntry (reserved64, header, offset);
  324 
  325         SerializeEntry (HiddenVolumeDataSize, header, offset);
  326         SerializeEntry (VolumeDataSize, header, offset);
  327         SerializeEntry (EncryptedAreaStart, header, offset);
  328         SerializeEntry (EncryptedAreaLength, header, offset);
  329         SerializeEntry (Flags, header, offset);
  330 
  331         if (SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
  332             || SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
  333             || SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
  334         {
  335             throw ParameterIncorrect (SRC_POS);
  336         }
  337 
  338         SerializeEntry (SectorSize, header, offset);
  339 
  340         offset = TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC;
  341         SerializeEntry (Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)), header, offset);
  342     }
  343 
  344     template <typename T>
  345     void VolumeHeader::SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const
  346     {
  347         offset += sizeof (T);
  348 
  349         if (offset > header.Size())
  350             throw ParameterIncorrect (SRC_POS);
  351 
  352         *reinterpret_cast<T *> (header.Get() + offset - sizeof (T)) = Endian::Big (entry);
  353     }
  354 
  355     void VolumeHeader::SetSize (uint32 headerSize)
  356     {
  357         HeaderSize = headerSize;
  358         EncryptedHeaderDataSize = HeaderSize - EncryptedHeaderDataOffset;
  359     }
  360 }