VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Main/Forms
AgeCommit message (Expand)AuthorFilesLines
2018-03-27Linux/MacOSX: make the benchmark dialog resize dynamically to accommodate the...Mounir IDRASSI1-0/+5
2018-03-18Update various copyright dates.Mounir IDRASSI1-4/+4
2017-06-23Update IDRIX copyright yearMounir IDRASSI62-64/+64
2017-04-26Update zlib copyright noticeMounir IDRASSI1-1/+1
2016-12-26Linux & MacOSX: automatically check TrueCryptMode in password dialog when sel...Mounir IDRASSI4-0/+24
2016-10-17Linux/MacOSX: correctly display Kuznyechik help page when link clicked. Remov...Mounir IDRASSI1-2/+0
2016-10-17Crypto: Use SIMD optimized Serpent implementation from Botan. 2.5x speed gain...Mounir IDRASSI1-1/+8
2016-10-17Linux/MacOSX: display error message when entered PIM is too big in the Volume...Mounir IDRASSI1-0/+1
2016-10-17Linux/MacOSX: add missing check for PIM max value on volume creation wizardMounir IDRASSI1-1/+2
2016-08-15Linux/MacOSX: Add help text for GOST89 and KuznyechikMounir IDRASSI1-0/+4
2016-06-02Crypto: Add support for Japanese encryption standard Camellia, including for ...Mounir IDRASSI1-0/+2
2016-05-13Linux: Fix gcc-6 compilation errors.Mounir IDRASSI1-2/+2
2016-05-10Remove trailing whitespaceDavid Foerster66-1732/+1732
2016-05-10Normalize all line terminatorsDavid Foerster3-33360/+33360
2016-05-04Windows/Linux/MacOSX: Set maximum PIM value to 2147468 in order to avoid havi...Mounir IDRASSI5-9/+11
2016-05-01Reset bogus executable permissionsDavid Foerster5-0/+0
2016-02-09Linux/MacOSX: add progress bar for mouse collected entropy in GUI of volume c...Mounir IDRASSI10-21/+146
2016-02-08Linux/MacOSX: add progress bar for mouse collected entropy in GUI for keyfile...Mounir IDRASSI7-10/+306
2016-01-30MacOSX: Support creation exFAT volumes on OSX using the built-in command newf...Mounir IDRASSI2-2/+8
2016-01-27Windows/Linux: Implement exFAT support.Mounir IDRASSI2-0/+4
2016-01-25Linux/MacOSX: remove unecessary XML resource string replacement of %hs, not n...Mounir IDRASSI1-2/+0
2016-01-25Linux/MacOSX: fix wrong AskYesNo method parameters use caused by mistake in p...Mounir IDRASSI1-1/+1
2016-01-25MacOSX: Add PIM value validity checks to workaround wxWidget bug that makes w...Mounir IDRASSI5-5/+50
2016-01-20Copyright: update dates to include 2016.Mounir IDRASSI64-65/+65
2015-11-30Linux/MacOSX: Implement Unicode passwords suppport. Make validation of parame...Mounir IDRASSI8-70/+126
2015-11-30Linux/MacOSX: Solve compilation issue following Windows Unicode rewriteMounir IDRASSI1-1/+1
2015-09-14Linux/MacOSX: workaround bug in old versions of g++ that are confused by meth...Mounir IDRASSI2-6/+6
2015-09-13Linux/MacOSX: Mask/unmask PIM value in GUI the same way as the passwordMounir IDRASSI7-20/+188
2015-08-06Update license information to reflect the use of a dual license Apache 2.0 an...Mounir IDRASSI62-287/+527
2015-07-25Linux: solve compilation error on OpenSUSE when linking against system wxWidg...Mounir IDRASSI1-1/+1
2015-07-19User Interface enhancements for PIMMounir IDRASSI11-50/+295
2015-07-11Use Pim name for internal variables instead of the old name PinMounir IDRASSI5-31/+31
2015-06-28Linux/MacOSX: Add dedicated PIM page in the volume creation wizard. Correct P...Mounir IDRASSI9-10/+659
2015-06-26Linux: don't ask for PIM if TrueCryptMode enabled, both in command line and GUIMounir IDRASSI5-9/+32
2015-06-24Linux/MacOSX: solve GUI layout issues although the volume creation wizard sti...Mounir IDRASSI4-9/+10
2015-06-24Linux/MacOSX: restore normal file mode to some source filesMounir IDRASSI11-0/+0
2015-06-24Linux/MacOSX: first dynamic mode implementationMounir IDRASSI11-33/+403
2015-04-19Linux: Correct wxWidgets assert warnings when displaying about/LegalNotice di...Mounir IDRASSI2-4/+2
2015-04-06Linux/MaxOSX: correctly detect type of internal exceptionsMounir IDRASSI1-4/+4
2015-04-06MacOSX: solve issue volumes not auto-dismounting when quitting VeraCrypt. res...Mounir IDRASSI2-2/+63
2015-04-05Linux/MacOSX: correctly handle some internal exception classes that were miss...Mounir IDRASSI1-0/+4
2015-02-28Linux/MacOSX: A configuration option for default hash and default TrueCrypt m...Mounir IDRASSI7-6/+385
2015-02-27Linux/MacOSX: Modify wxFormBuilder generated files directly to solve the 'X' ...Mounir IDRASSI1-6/+6
2015-02-27Revert "Linux/MacOSX: solve the 'X' icon not closing some dialog. This was ca...Mounir IDRASSI8-14/+14
2015-02-16Linux/MacOSX: solve the 'X' icon not closing some dialog. This was caused by ...Mounir IDRASSI8-14/+14
2015-02-13Linux: Perform a quick NTFS formatting by adding the "-f" switch to mkfs.ntfs...Mounir IDRASSI1-0/+4
2015-02-08Linux/MacOSX: use command line values of TrueCryptMode and PRF as defaults fo...Mounir IDRASSI6-9/+33
2015-01-04Linux/MacOSX: Add wait dialog to the benchmark computation. Correct handling ...Mounir IDRASSI4-22/+42
2015-01-04Linux/MacOSX: make the cancel button work on the preferences dialog.Mounir IDRASSI1-1/+1
2015-01-04Linux/MacOSX: change cascade encryption naming format in the UI as it was don...Mounir IDRASSI3-4/+4
#0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 Legal Notice: Some portions of the source code contained in this file were
 derived from the source code of Encryption for the Masses 2.02a, which is
 Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
 Agreement for Encryption for the Masses'. Modifications and additions to
 the original source code (contained in this file) and all other portions
 of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
 and are governed by the TrueCrypt License 3.0 the full text of which is
 contained in the file License.txt included in TrueCrypt binary and source
 code distribution packages. */

#include "Tcdefs.h"

#include "Crypto.h"
#include "Volumes.h"
#include "Password.h"
#include "Dlgcode.h"
#include "Language.h"
#include "Pkcs5.h"
#include "Endian.h"
#include "Random.h"

#include <io.h>

void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword,
			 HWND hVerify, unsigned char *szPassword,
			 char *szVerify,
			 BOOL keyFilesEnabled)
{
	char szTmp1[MAX_PASSWORD + 1];
	char szTmp2[MAX_PASSWORD + 1];
	int k = GetWindowTextLength (hPassword);
	BOOL bEnable = FALSE;

	if (hwndDlg);		/* Remove warning */

	GetWindowText (hPassword, szTmp1, sizeof (szTmp1));
	GetWindowText (hVerify, szTmp2, sizeof (szTmp2));

	if (strcmp (szTmp1, szTmp2) != 0)
		bEnable = FALSE;
	else
	{
		if (k >= MIN_PASSWORD || keyFilesEnabled)
			bEnable = TRUE;
		else
			bEnable = FALSE;
	}

	if (szPassword != NULL)
		memcpy (szPassword, szTmp1, sizeof (szTmp1));

	if (szVerify != NULL)
		memcpy (szVerify, szTmp2, sizeof (szTmp2));

	burn (szTmp1, sizeof (szTmp1));
	burn (szTmp2, sizeof (szTmp2));

	EnableWindow (hButton, bEnable);
}


BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
{
	int i, len;
	
	if (hPassword == NULL)
	{
		if (ptrPw)
		{
			unsigned char *pw;
			len = ptrPw->Length;
			pw = (unsigned char *) ptrPw->Text;

			for (i = 0; i < len; i++)
			{
				if (pw[i] >= 0x7f || pw[i] < 0x20)	// A non-ASCII or non-printable character?
					return FALSE;
			}
		}
		else
			return FALSE;
	}
	else
	{
		wchar_t s[MAX_PASSWORD + 1];
		len = GetWindowTextLength (hPassword);

		if (len > MAX_PASSWORD)
			return FALSE; 

		GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t));

		for (i = 0; i < len; i++)
		{
			if (s[i] >= 0x7f || s[i] < 0x20)	// A non-ASCII or non-printable character?
				break;
		}

		burn (s, sizeof(s));

		if (i < len)
			return FALSE; 
	}

	return TRUE;
}


BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem)
{
	if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING)
	{
#ifndef _DEBUG
		if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES)
			return FALSE;
#endif
	}
	return TRUE;
}

int ChangePwd (const char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, int wipePassCount, HWND hwndDlg)
{
	int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
	char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
	char szDosDevice[TC_MAX_PATH];
	char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
	PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
	void *dev = INVALID_HANDLE_VALUE;
	DWORD dwError;
	DWORD bytesRead;
	BOOL bDevice;
	unsigned __int64 hostSize = 0;
	int volumeType;
	int wipePass;
	FILETIME ftCreationTime;
	FILETIME ftLastWriteTime;
	FILETIME ftLastAccessTime;
	BOOL bTimeStampValid = FALSE;
	LARGE_INTEGER headerOffset;
	BOOL backupHeader;
	DISK_GEOMETRY driveInfo;

	if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;

	if (wipePassCount <= 0)
	{
      nStatus = ERR_PARAMETER_INCORRECT;
      handleError (hwndDlg, nStatus);
      return nStatus;
	}

   if (!lpszVolume)
   {
      nStatus = ERR_OUTOFMEMORY;
      handleError (hwndDlg, nStatus);
      return nStatus;
   }

	WaitCursor ();

	CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice);

	if (bDevice == FALSE)
	{
		strcpy (szCFDevice, szDiskFile);
	}
	else
	{
		nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice),FALSE);
		
		if (nDosLinkCreated != 0)
			goto error;
	}

	dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

	if (dev == INVALID_HANDLE_VALUE) 
		goto error;

	if (bDevice)
	{
		/* This is necessary to determine the hidden volume header offset */

		if (dev == INVALID_HANDLE_VALUE)
		{
			goto error;
		}
		else
		{
			PARTITION_INFORMATION diskInfo;
			DWORD dwResult;
			BOOL bResult;

			bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
				&driveInfo, sizeof (driveInfo), &dwResult, NULL);

			if (!bResult)
				goto error;

			bResult = GetPartitionInfo (lpszVolume, &diskInfo);

			if (bResult)
			{
				hostSize = diskInfo.PartitionLength.QuadPart;
			}
			else
			{
				hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
					driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
			}

			if (hostSize == 0)
			{
				nStatus = ERR_VOL_SIZE_WRONG;
				goto error;
			}
		}
	}
	else
	{
		LARGE_INTEGER fileSize;
		if (!GetFileSizeEx (dev, &fileSize))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}

		hostSize = fileSize.QuadPart;
	}

	if (Randinit ())
		goto error;

	if (!bDevice && bPreserveTimestamp)
	{
		if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
			bTimeStampValid = FALSE;
		else
			bTimeStampValid = TRUE;
	}

	for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
	{
		// Seek the volume header
		switch (volumeType)
		{
		case TC_VOLUME_TYPE_NORMAL:
			headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
			break;

		case TC_VOLUME_TYPE_HIDDEN:
			if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
				continue;

			headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
			break;

		case TC_VOLUME_TYPE_HIDDEN_LEGACY:
			if (bDevice && driveInfo.BytesPerSector != TC_SECTOR_SIZE_LEGACY)
				continue;

			headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
			break;
		}

		if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}

		/* Read in volume header */
		if (!ReadEffectiveVolumeHeader (bDevice, dev, buffer, &bytesRead))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}

		if (bytesRead != sizeof (buffer))
		{
			// Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS 
			memset (buffer, 0, sizeof (buffer));
		}

		/* Try to decrypt the header */

		nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
		if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
			nStatus = 0;	// We can ignore this error here

		if (nStatus == ERR_PASSWORD_WRONG)
		{
			continue;		// Try next volume type
		}
		else if (nStatus != 0)
		{
			cryptoInfo = NULL;
			goto error;
		}
		else 
			break;
	}

	if (nStatus != 0)
	{
		cryptoInfo = NULL;
		goto error;
	}

	if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
	{
		nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
		goto error;
	}

	// Change the PKCS-5 PRF if requested by user
	if (pkcs5 != 0)
		cryptoInfo->pkcs5 = pkcs5;

	RandSetHashFunction (cryptoInfo->pkcs5);

	NormalCursor();
	UserEnrichRandomPool (hwndDlg);
	EnableElevatedCursorChange (hwndDlg);
	WaitCursor();

	/* Re-encrypt the volume header */ 
	backupHeader = FALSE;

	while (TRUE)
	{
		/* The header will be re-encrypted wipePassCount times to prevent adversaries from using 
		techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
		to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
		times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
		impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
		valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
		recommends. During each pass we will write a valid working header. Each pass will use the same master
		key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
		item that will be different for each pass will be the salt. This is sufficient to cause each "version"
		of the header to differ substantially and in a random manner from the versions written during the
		other passes. */

		for (wipePass = 0; wipePass < wipePassCount; wipePass++)
		{
			// Prepare new volume header
			nStatus = CreateVolumeHeaderInMemory (FALSE,
				buffer,
				cryptoInfo->ea,
				cryptoInfo->mode,
				newPassword,
				cryptoInfo->pkcs5,
				cryptoInfo->master_keydata,
				&ci,
				cryptoInfo->VolumeSize.Value,
				(volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0,
				cryptoInfo->EncryptedAreaStart.Value,
				cryptoInfo->EncryptedAreaLength.Value,
				cryptoInfo->RequiredProgramVersion,
				cryptoInfo->HeaderFlags,
				cryptoInfo->SectorSize,
				wipePass < wipePassCount - 1);

			if (ci != NULL)
				crypto_close (ci);

			if (nStatus != 0)
				goto error;

			if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
			{
				nStatus = ERR_OS_ERROR;
				goto error;
			}

			if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
			{
				nStatus = ERR_OS_ERROR;
				goto error;
			}

			if (bDevice
				&& !cryptoInfo->LegacyVolume
				&& !cryptoInfo->hiddenVolume
				&& cryptoInfo->HeaderVersion == 4
				&& (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
				&& (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
			{
				nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
				if (nStatus != ERR_SUCCESS)
					goto error;
			}

			FlushFileBuffers (dev);
		}

		if (backupHeader || cryptoInfo->LegacyVolume)
			break;
			
		backupHeader = TRUE;
		headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
	}

	/* Password successfully changed */
	nStatus = 0;

error:
	dwError = GetLastError ();

	burn (buffer, sizeof (buffer));

	if (cryptoInfo != NULL)
		crypto_close (cryptoInfo);

	if (bTimeStampValid)
		SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);

	if (dev != INVALID_HANDLE_VALUE)
		CloseHandle ((HANDLE) dev);

	if (nDosLinkCreated == 0)
		RemoveFakeDosName (szDiskFile, szDosDevice);

	RandStop (FALSE);
	NormalCursor ();

	SetLastError (dwError);

	if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
		&& bDevice
		&& !UacElevated
		&& IsUacSupported ())
		return nStatus;

	if (nStatus != 0)
		handleError (hwndDlg, nStatus);

	return nStatus;
}