VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/doc/html/Changing Passwords and Keyfiles.html
blob: 2a9a7ed69e93e318f5cc7607ce0e6e78e4fee833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>VeraCrypt - Free Open source disk encryption with strong security for the Paranoid</title>
<meta name="description" content="VeraCrypt is free open-source disk encryption software for Windows, Mac OS X and Linux. In case an attacker forces you to reveal the password, VeraCrypt provides plausible deniability. In contrast to file encryption, data encryption performed by VeraCrypt is real-time (on-the-fly), automatic, transparent, needs very little memory, and does not involve temporary unencrypted files."/>
<meta name="keywords" content="encryption, security"/>
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div>
<a href="Documentation.html"><img src="VeraCrypt128x128.png" alt="VeraCrypt"/></a>
</div>

<div id="menu">
	<ul>
	  <li><a href="Home.html">Home</a></li>
	  <li><a href="/code/">Source Code</a></li>
	  <li><a href="Downloads.html">Downloads</a></li>
	  <li><a class="active" href="Documentation.html">Documentation</a></li>
	  <li><a href="Donation.html">Donate</a></li>
	  <li><a href="https://sourceforge.net/p/veracrypt/discussion/" target="_blank">Forums</a></li>
	</ul>
</div>

<div>
<p>
<a href="Documentation.html">Documentation</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px">
<a href="Security%20Requirements%20and%20Precautions.html">Security Requirements and Precautions</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px">
<a href="Changing%20Passwords%20and%20Keyfiles.html">Changing Passwords and Keyfiles</a>
</p></div>

<div class="wikidoc">
<h1>Changing Passwords and Keyfiles</h1>
<p>Note that the volume header (which is encrypted with a header key derived from a password/keyfile) contains the master key (not to be confused with the password) with which the volume is encrypted. If an adversary is allowed to make a copy of your volume
 before you change the volume password and/or keyfile(s), he may be able to use his copy or fragment (the old header) of the VeraCrypt volume to mount your volume using a compromised password and/or compromised keyfiles that were necessary to mount the volume
 before you changed the volume password and/or keyfile(s).<br>
<br>
If you are not sure whether an adversary knows your password (or has your keyfiles) and whether he has a copy of your volume when you need to change its password and/or keyfiles, it is strongly recommended that you create a new VeraCrypt volume and move files
 from the old volume to the new volume (the new volume will have a different master key).<br>
<br>
Also note that if an adversary knows your password (or has your keyfiles) and has access to your volume, he may be able to retrieve and keep its master key. If he does, he may be able to decrypt your volume even after you change its password and/or keyfile(s)
 (because the master key does not change when you change the volume password and/or keyfiles). In such a case, create a new VeraCrypt volume and move all files from the old volume to this new one.<br>
<br>
The following sections of this chapter contain additional information pertaining to possible security issues connected with changing passwords and/or keyfiles:</p>
<ul>
<li><a href="Security%20Requirements%20and%20Precautions.html"><em>Security Requirements and Precautions</em></a>
</li><li><a href="Journaling%20File%20Systems.html"><em>Journaling File Systems</em></a>
</li><li><a href="Defragmenting.html"><em>Defragmenting</em></a>
</li><li><a href="Reallocated%20Sectors.html"><em>Reallocated Sectors</em></a>
</li></ul>
</div><div class="ClearBoth"></div></body></html>
"p">} VolumeCreator::~VolumeCreator () { } void VolumeCreator::Abort () { AbortRequested = true; } void VolumeCreator::CheckResult () { if (ThreadException) ThreadException->Throw(); } void VolumeCreator::CreationThread () { try { uint64 endOffset; uint64 filesystemSize = Layout->GetDataSize (HostSize); if (filesystemSize < 1) throw ParameterIncorrect (SRC_POS); DataStart = Layout->GetDataOffset (HostSize); WriteOffset = DataStart; endOffset = DataStart + Layout->GetDataSize (HostSize); VolumeFile->SeekAt (DataStart); // Create filesystem if (Options->Filesystem == VolumeCreationOptions::FilesystemType::FAT) { if (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_SECTOR_COUNT * Options->SectorSize) throw ParameterIncorrect (SRC_POS); struct WriteSectorCallback : public FatFormatter::WriteSectorCallback { WriteSectorCallback (VolumeCreator *creator) : Creator (creator), OutputBuffer (File::GetOptimalWriteSize()), OutputBufferWritePos (0) { } virtual bool operator() (const BufferPtr &sector) { OutputBuffer.GetRange (OutputBufferWritePos, sector.Size()).CopyFrom (sector); OutputBufferWritePos += sector.Size(); if (OutputBufferWritePos >= OutputBuffer.Size()) FlushOutputBuffer(); return !Creator->AbortRequested; } void FlushOutputBuffer () { if (OutputBufferWritePos > 0) { Creator->Options->EA->EncryptSectors (OutputBuffer.GetRange (0, OutputBufferWritePos), Creator->WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, OutputBufferWritePos / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); Creator->VolumeFile->Write (OutputBuffer.GetRange (0, OutputBufferWritePos)); Creator->WriteOffset += OutputBufferWritePos; Creator->SizeDone.Set (Creator->WriteOffset - Creator->DataStart); OutputBufferWritePos = 0; } } VolumeCreator *Creator; SecureBuffer OutputBuffer; size_t OutputBufferWritePos; }; WriteSectorCallback sectorWriter (this); FatFormatter::Format (sectorWriter, filesystemSize, Options->FilesystemClusterSize, Options->SectorSize); sectorWriter.FlushOutputBuffer(); } if (!Options->Quick) { // Empty sectors are encrypted with different key to randomize plaintext Core->RandomizeEncryptionAlgorithmKey (Options->EA); SecureBuffer outputBuffer (File::GetOptimalWriteSize()); uint64 dataFragmentLength = outputBuffer.Size(); while (!AbortRequested && WriteOffset < endOffset) { if (WriteOffset + dataFragmentLength > endOffset) dataFragmentLength = endOffset - WriteOffset; outputBuffer.Zero(); Options->EA->EncryptSectors (outputBuffer, WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, dataFragmentLength / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); VolumeFile->Write (outputBuffer, (size_t) dataFragmentLength); WriteOffset += dataFragmentLength; SizeDone.Set (WriteOffset - DataStart); } } if (!AbortRequested) { SizeDone.Set (Options->Size); // Backup header SecureBuffer backupHeader (Layout->GetHeaderSize()); SecureBuffer backupHeaderSalt (VolumeHeader::GetSaltSize()); RandomNumberGenerator::GetData (backupHeaderSalt); Options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, Options->Pim, backupHeaderSalt); Layout->GetHeader()->EncryptNew (backupHeader, backupHeaderSalt, HeaderKey, Options->VolumeHeaderKdf); if (Options->Quick || Options->Type == VolumeType::Hidden) VolumeFile->SeekEnd (Layout->GetBackupHeaderOffset()); VolumeFile->Write (backupHeader); if (Options->Type == VolumeType::Normal) { // Write fake random header to space reserved for hidden volume header VolumeLayoutV2Hidden hiddenLayout; shared_ptr <VolumeHeader> hiddenHeader (hiddenLayout.GetHeader()); SecureBuffer hiddenHeaderBuffer (hiddenLayout.GetHeaderSize()); VolumeHeaderCreationOptions headerOptions; headerOptions.EA = Options->EA; headerOptions.Kdf = Options->VolumeHeaderKdf; headerOptions.Type = VolumeType::Hidden; headerOptions.SectorSize = Options->SectorSize; headerOptions.VolumeDataStart = HostSize - hiddenLayout.GetHeaderSize() * 2 - Options->Size; headerOptions.VolumeDataSize = hiddenLayout.GetMaxDataSize (Options->Size); // Master data key SecureBuffer hiddenMasterKey(Options->EA->GetKeySize() * 2); RandomNumberGenerator::GetData (hiddenMasterKey); headerOptions.DataKey = hiddenMasterKey; // PKCS5 salt SecureBuffer hiddenSalt (VolumeHeader::GetSaltSize()); RandomNumberGenerator::GetData (hiddenSalt); headerOptions.Salt = hiddenSalt; // Header key SecureBuffer hiddenHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); RandomNumberGenerator::GetData (hiddenHeaderKey); headerOptions.HeaderKey = hiddenHeaderKey; hiddenHeader->Create (backupHeader, headerOptions); VolumeFile->Write (backupHeader); } VolumeFile->Flush(); } } catch (Exception &e) { ThreadException.reset (e.CloneNew()); } catch (exception &e) { ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e))); } catch (...) { ThreadException.reset (new UnknownException (SRC_POS)); } VolumeFile.reset(); mProgressInfo.CreationInProgress = false; } void VolumeCreator::CreateVolume (shared_ptr <VolumeCreationOptions> options) { EncryptionTest::TestAll(); { #ifdef TC_UNIX // Temporarily take ownership of a device if the user is not an administrator UserId origDeviceOwner ((uid_t) -1); if (!Core->HasAdminPrivileges() && options->Path.IsDevice()) { origDeviceOwner = FilesystemPath (wstring (options->Path)).GetOwner(); Core->SetFileOwner (options->Path, UserId (getuid())); } finally_do_arg2 (FilesystemPath, options->Path, UserId, origDeviceOwner, { if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); }); #endif VolumeFile.reset (new File); VolumeFile->Open (options->Path, (options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite, File::ShareNone); HostSize = VolumeFile->Length(); } try { // Sector size if (options->Path.IsDevice()) { options->SectorSize = VolumeFile->GetDeviceSectorSize(); if (options->SectorSize < TC_MIN_VOLUME_SECTOR_SIZE || options->SectorSize > TC_MAX_VOLUME_SECTOR_SIZE #if !defined (TC_LINUX) && !defined (TC_MACOSX) || options->SectorSize != TC_SECTOR_SIZE_LEGACY #endif || options->SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0) { throw UnsupportedSectorSize (SRC_POS); } } else options->SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME; // Volume layout switch (options->Type) { case VolumeType::Normal: Layout.reset (new VolumeLayoutV2Normal()); break; case VolumeType::Hidden: Layout.reset (new VolumeLayoutV2Hidden()); if (HostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE) throw ParameterIncorrect (SRC_POS); break; default: throw ParameterIncorrect (SRC_POS); } // Volume header shared_ptr <VolumeHeader> header (Layout->GetHeader()); SecureBuffer headerBuffer (Layout->GetHeaderSize()); VolumeHeaderCreationOptions headerOptions; headerOptions.EA = options->EA; headerOptions.Kdf = options->VolumeHeaderKdf; headerOptions.Type = options->Type; headerOptions.SectorSize = options->SectorSize; if (options->Type == VolumeType::Hidden) headerOptions.VolumeDataStart = HostSize - Layout->GetHeaderSize() * 2 - options->Size; else headerOptions.VolumeDataStart = Layout->GetHeaderSize() * 2; headerOptions.VolumeDataSize = Layout->GetMaxDataSize (options->Size); if (headerOptions.VolumeDataSize < 1) throw ParameterIncorrect (SRC_POS); // Master data key MasterKey.Allocate (options->EA->GetKeySize() * 2); RandomNumberGenerator::GetData (MasterKey); // check that first half of MasterKey is different from its second half. If they are the same, through an exception // cf CCSS,NSA comment at page 3: https://csrc.nist.gov/csrc/media/Projects/crypto-publication-review-project/documents/initial-comments/sp800-38e-initial-public-comments-2021.pdf if (memcmp (MasterKey.Ptr(), MasterKey.Ptr() + MasterKey.Size() / 2, MasterKey.Size() / 2) == 0) throw AssertionFailed (SRC_POS); headerOptions.DataKey = MasterKey; // PKCS5 salt SecureBuffer salt (VolumeHeader::GetSaltSize()); RandomNumberGenerator::GetData (salt); headerOptions.Salt = salt; // Header key HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize()); PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVSupportEnabled); options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt); headerOptions.HeaderKey = HeaderKey; header->Create (headerBuffer, headerOptions); // Write new header if (Layout->GetHeaderOffset() >= 0) VolumeFile->SeekAt (Layout->GetHeaderOffset()); else VolumeFile->SeekEnd (Layout->GetHeaderOffset()); VolumeFile->Write (headerBuffer); if (options->Type == VolumeType::Normal) { // Write fake random header to space reserved for hidden volume header VolumeLayoutV2Hidden hiddenLayout; shared_ptr <VolumeHeader> hiddenHeader (hiddenLayout.GetHeader()); SecureBuffer hiddenHeaderBuffer (hiddenLayout.GetHeaderSize()); headerOptions.Type = VolumeType::Hidden; headerOptions.VolumeDataStart = HostSize - hiddenLayout.GetHeaderSize() * 2 - options->Size; headerOptions.VolumeDataSize = hiddenLayout.GetMaxDataSize (options->Size); // Master data key SecureBuffer hiddenMasterKey(options->EA->GetKeySize() * 2); RandomNumberGenerator::GetData (hiddenMasterKey); headerOptions.DataKey = hiddenMasterKey; // PKCS5 salt SecureBuffer hiddenSalt (VolumeHeader::GetSaltSize()); RandomNumberGenerator::GetData (hiddenSalt); headerOptions.Salt = hiddenSalt; // Header key SecureBuffer hiddenHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); RandomNumberGenerator::GetData (hiddenHeaderKey); headerOptions.HeaderKey = hiddenHeaderKey; hiddenHeader->Create (headerBuffer, headerOptions); VolumeFile->Write (headerBuffer); } // Data area keys options->EA->SetKey (MasterKey.GetRange (0, options->EA->GetKeySize())); #ifdef WOLFCRYPT_BACKEND shared_ptr <EncryptionMode> mode (new EncryptionModeWolfCryptXTS ()); options->EA->SetKeyXTS (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize())); #else shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ()); #endif mode->SetKey (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize())); options->EA->SetMode (mode); Options = options; AbortRequested = false; mProgressInfo.CreationInProgress = true; struct ThreadFunctor : public Functor { ThreadFunctor (VolumeCreator *creator) : Creator (creator) { } virtual void operator() () { Creator->CreationThread (); } VolumeCreator *Creator; }; Thread thread; thread.Start (new ThreadFunctor (this)); } catch (...) { VolumeFile.reset(); throw; } } VolumeCreator::KeyInfo VolumeCreator::GetKeyInfo () const { KeyInfo info; info.HeaderKey = HeaderKey; info.MasterKey = MasterKey; return info; } VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo () { mProgressInfo.SizeDone = SizeDone.Get(); return mProgressInfo; } }