/* Derived from source code of TrueCrypt 7.1a, which is Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2016 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "System.h" #include "Platform/SystemInfo.h" #ifdef TC_UNIX #include #include "Platform/Unix/Process.h" #endif #include "Core/RandomNumberGenerator.h" #include "Core/VolumeCreator.h" #include "Main/Application.h" #include "Main/GraphicUserInterface.h" #include "Main/Resources.h" #include "VolumeCreationWizard.h" #include "EncryptionOptionsWizardPage.h" #include "InfoWizardPage.h" #include "ProgressWizardPage.h" #include "SingleChoiceWizardPage.h" #include "VolumeCreationProgressWizardPage.h" #include "VolumeFormatOptionsWizardPage.h" #include "VolumeLocationWizardPage.h" #include "VolumePasswordWizardPage.h" #include "VolumePimWizardPage.h" #include "VolumeSizeWizardPage.h" #include "WaitDialog.h" namespace VeraCrypt { VolumeCreationWizard::VolumeCreationWizard (wxWindow* parent) : WizardFrame (parent), CrossPlatformSupport (true), DisplayKeyInfo (false), LargeFilesSupport (false), QuickFormatEnabled (false), SelectedFilesystemClusterSize (0), SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT), SelectedVolumeHostType (VolumeHostType::File), SelectedVolumeType (VolumeType::Normal), Pim (0), SectorSize (0), VolumeSize (0) { RandomNumberGenerator::Start(); SetTitle (LangString["INTRO_TITLE"]); SetImage (Resources::GetVolumeCreationWizardBitmap (Gui->GetCharHeight (this) * 21)); SetMaxStaticTextWidth (55); SetStep (Step::VolumeHostType); class Timer : public wxTimer { public: Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } void Notify() { Wizard->OnRandomPoolUpdateTimer(); } VolumeCreationWizard *Wizard; }; RandomPoolUpdateTimer.reset (dynamic_cast (new Timer (this))); RandomPoolUpdateTimer->Start (200); } VolumeCreationWizard::~VolumeCreationWizard () { } WizardPage *VolumeCreationWizard::GetPage (WizardStep step) { switch (step) { case Step::VolumeHostType: { ClearHistory(); OuterVolume = false; LargeFilesSupport = false; QuickFormatEnabled = false; Pim = 0; SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); page->SetMinSize (wxSize (Gui->GetCharWidth (this) * 58, Gui->GetCharHeight (this) * 18 + 5)); page->SetPageTitle (LangString["INTRO_TITLE"]); page->AddChoice (VolumeHostType::File, LangString["IDC_FILE_CONTAINER"], LangString["IDT_FILE_CONTAINER"], L"introcontainer", LangString["IDC_MORE_INFO_ON_CONTAINERS"]); page->AddChoice (VolumeHostType::Device, _("Create a volume within a partition/&drive"), _("Formats and encrypts a non-system partition, entire external or secondary drive, entire USB stick, etc.")); page->SetSelection (SelectedVolumeHostType); return page; } case Step::VolumeType: { SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); page->SetPageTitle (LangString["VOLUME_TYPE_TITLE"]); page->AddChoice (VolumeType::Normal, LangString["IDC_STD_VOL"], LangString["NORMAL_VOLUME_TYPE_HELP"]); page->AddChoice (VolumeType::Hidden, LangString["IDC_HIDDEN_VOL"], LangString["HIDDEN_VOLUME_TYPE_HELP"], L"hiddenvolume", LangString["IDC_HIDDEN_VOL_HELP"]); page->SetSelection (SelectedVolumeType); return page; } case Step::VolumeLocation: { VolumeLocationWizardPage *page = new VolumeLocationWizardPage (GetPageParent(), SelectedVolumeHostType); page->SetPageTitle (LangString["VOLUME_LOCATION"]); if (SelectedVolumeType == VolumeType::Hidden) page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP_HIDDEN_HOST_VOL"]); else page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP" : "DEVICE_HELP_NO_INPLACE"]); page->SetVolumePath (SelectedVolumePath); return page; } case Step::EncryptionOptions: { EncryptionOptionsWizardPage *page = new EncryptionOptionsWizardPage (GetPageParent()); if (OuterVolume) page->SetPageTitle (LangString["CIPHER_HIDVOL_HOST_TITLE"]); else if (SelectedVolumeType == VolumeType::Hidden) page->SetPageTitle (LangString["CIPHER_HIDVOL_TITLE"]); else page->SetPageTitle (LangString["CIPHER_TITLE"]); page->SetEncryptionAlgorithm (SelectedEncryptionAlgorithm); page->SetHash (SelectedHash); return page; } case Step::VolumeSize: { wxString freeSpaceText; wxString pageTitle; wxString pageText; if (OuterVolume) { pageTitle = LangString["SIZE_HIDVOL_HOST_TITLE"]; pageText = LangString["SIZE_HELP_HIDDEN_HOST_VOL"]; } else if (SelectedVolumeType == VolumeType::Hidden) { pageTitle = LangString["SIZE_HIDVOL_TITLE"]; pageText = LangString["SIZE_HELP_HIDDEN_VOL"] + L"\n\n" + _("Please note that if your operating system does not allocate files from the beginning of the free space, the maximum possible hidden volume size may be much smaller than the size of the free space on the outer volume. This not a bug in VeraCrypt but a limitation of the operating system."); freeSpaceText = StringFormatter (_("Maximum possible hidden volume size for this volume is {0}."), Gui->SizeToString (MaxHiddenVolumeSize)); } else { pageTitle = LangString["SIZE_TITLE"]; pageText = LangString["VOLUME_SIZE_HELP"]; } VolumeSizeWizardPage *page = new VolumeSizeWizardPage (GetPageParent(), SelectedVolumePath, SectorSize, freeSpaceText); page->SetPageTitle (pageTitle); page->SetPageText (pageText); if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden) page->SetMaxVolumeSize (MaxHiddenVolumeSize); else page->SetVolumeSize (VolumeSize); if (OuterVolume) page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_HOST_SIZE); else if (SelectedVolumeType == VolumeType::Hidden) page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_SIZE); else page->SetMinVolumeSize (TC_MIN_VOLUME_SIZE); return page; } case Step::VolumePassword: { VolumePasswordWizardPage *page = new VolumePasswordWizardPage (GetPageParent(), Password, Keyfiles); page->EnableUsePim (); // force displaying "Use PIM" page->SetPimSelected (Pim > 0); if (OuterVolume) page->SetPageTitle (LangString["PASSWORD_HIDVOL_HOST_TITLE"]); else if (SelectedVolumeType == VolumeType::Hidden) page->SetPageTitle (LangString["PASSWORD_HIDVOL_TITLE"]); else page->SetPageTitle (LangString["PASSWORD_TITLE"]); page->SetPageText (LangString[OuterVolume ? "PASSWORD_HIDDENVOL_HOST_HELP" : "PASSWORD_HELP"]); return page; } case Step::VolumePim: { VolumePimWizardPage *page = new VolumePimWizardPage (GetPageParent()); if (OuterVolume) page->SetPageTitle (LangString["PIM_HIDVOL_HOST_TITLE"]); else if (SelectedVolumeType == VolumeType::Hidden) page->SetPageTitle (LangString["PIM_HIDVOL_TITLE"]); else page->SetPageTitle (LangString["PIM_TITLE"]); page->SetPageText (LangString["PIM_HELP"]); page->SetVolumePim (Pim); return page; } case Step
/*
 Derived from source code of TrueCrypt 7.1a, which is
 Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
 by the TrueCrypt License 3.0.

 Modifications and additions to the original source code (contained in this file)
 and all other portions of this file are Copyright (c) 2013-2016 IDRIX
 and are governed by the Apache License 2.0 the full text of which is
 contained in the file License.txt included in VeraCrypt binary and source
 code distribution packages.
*/

#include "System.h"
#include "Main/GraphicUserInterface.h"
#include "Main/Resources.h"
#include "DeviceSelectionDialog.h"

namespace VeraCrypt
{
	DeviceSelectionDialog::DeviceSelectionDialog (wxWindow* parent)
		: DeviceSelectionDialogBase (parent)
	{
		wxBusyCursor busy;

		list <int> colPermilles;

		DeviceListCtrl->InsertColumn (ColumnDevice, LangString["DEVICE"], wxLIST_FORMAT_LEFT, 1);
		colPermilles.push_back (447);
#ifdef TC_WINDOWS
		DeviceListCtrl->InsertColumn (ColumnDrive, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1);
		colPermilles.push_back (91);
#endif
		DeviceListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1);
		colPermilles.push_back (153);
#ifdef TC_WINDOWS
		DeviceListCtrl->InsertColumn (ColumnName, LangString["LABEL"], wxLIST_FORMAT_LEFT, 1);
		colPermilles.push_back (307);
#else
		DeviceListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1);
		colPermilles.push_back (396);
#endif

		wxImageList *imageList = new wxImageList (16, 12, true);
		imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap());
		DeviceListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL);

		DeviceList = Core->GetHostDevices();

		foreach_ref (HostDevice &device, DeviceList)
		{
			if (device.Size == 0)
				continue;

			vector <wstring> fields (DeviceListCtrl->GetColumnCount());

			if (DeviceListCtrl->GetItemCount() > 0)
				Gui->AppendToListCtrl (DeviceListCtrl, fields);

#ifdef TC_WINDOWS
			fields[ColumnDevice] = StringFormatter (L"{0} {1}:", _("Harddisk"), device.SystemNumber);
			fields[ColumnDrive] = device.MountPoint;
			fields[ColumnName] = device.Name;
#else
			fields[ColumnDevice] = wstring (device.Path) + L":";
			fields[ColumnMountPoint] = device.MountPoint;
#endif
			fields[ColumnSize] = Gui->SizeToString (device.Size);
			Gui->AppendToListCtrl (DeviceListCtrl, fields, 0, &device);

			foreach_ref (HostDevice &partition, device.Partitions)
			{
				fields[ColumnDevice] =
#ifndef TC_WINDOWS
					wstring (L"      ") +
#endif
					wstring (partition.Path);

#ifdef TC_WINDOWS
				fields[ColumnDrive] = partition.MountPoint;
				fields[ColumnName] = partition.Name;
#else
				fields[ColumnMountPoint] = partition.MountPoint;
#endif
				fields[ColumnSize] = Gui->SizeToString (partition.Size);
				Gui->AppendToListCtrl (DeviceListCtrl, fields, -1, &partition);
			}
		}

		Gui->SetListCtrlWidth (DeviceListCtrl, 73);
		Gui->SetListCtrlHeight (DeviceListCtrl, 16);
		Gui->SetListCtrlColumnWidths (DeviceListCtrl, colPermilles);

		Fit();
		Layout();
		Center();

		StdButtonsOK->Disable();
		StdButtonsOK->SetDefault();
	}

	void DeviceSelectionDialog::OnListItemActivated (wxListEvent& event)
	{
		if (StdButtonsOK->IsEnabled())
			EndModal (wxID_OK);
	}

	void DeviceSelectionDialog::OnListItemDeselected (wxListEvent& event)
	{
		if (DeviceListCtrl->GetSelectedItemCount() == 0)
			StdButtonsOK->Disable();
	}

	void DeviceSelectionDialog::OnListItemSelected (wxListEvent& event)
	{
		HostDevice *device = (HostDevice *) (event.GetItem().GetData());
		if (device)
		{
			SelectedDevice = *device;
			StdButtonsOK->Enable();
		}
		else
			StdButtonsOK->Disable();
	}
}
if (SelectedVolumePath.IsDevice()) { wxString confirmMsg = LangString["OVERWRITEPROMPT_DEVICE"]; if (!Gui->AskYesNo (wxString::Format (confirmMsg, wxString (_("DEVICE")).c_str(), wstring (SelectedVolumePath).c_str(), L""), false, true)) return GetCurrentStep(); } else if (FilesystemPath (wstring (SelectedVolumePath)).IsFile()) { wxString confirmMsg = LangString["OVERWRITEPROMPT"]; if (!Gui->AskYesNo (wxString::Format (confirmMsg, wstring (SelectedVolumePath).c_str()), false, true)) return GetCurrentStep(); } } AbortRequested = false; AbortConfirmationPending = false; CreationAborted = false; SetWorkInProgress (true); UpdateControls(); Gui->BeginInteractiveBusyState (this); try { make_shared_auto (VolumeCreationOptions, options); options->Filesystem = SelectedFilesystemType; options->FilesystemClusterSize = SelectedFilesystemClusterSize; options->SectorSize = SectorSize; options->EA = SelectedEncryptionAlgorithm; options->Password = Password; options->Pim = Pim; options->Keyfiles = Keyfiles; options->Path = SelectedVolumePath; options->Quick = QuickFormatEnabled; options->Size = VolumeSize; options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType; options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash, false); Creator.reset (new VolumeCreator); VolumeCreatorThreadRoutine routine(options, Creator); Gui->ExecuteWaitThreadRoutine (this, &routine); page->SetKeyInfo (Creator->GetKeyInfo()); class Timer : public wxTimer { public: Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } void Notify() { Wizard->OnProgressTimer(); } VolumeCreationWizard *Wizard; }; page->SetProgressRange (options->Size); page->SetProgressState (true); ProgressTimer.reset (dynamic_cast (new Timer (this))); ProgressTimer->Start (50); } catch (Exception &e) { CreationAborted = true; OnVolumeCreatorFinished(); Gui->ShowError (e); } } return GetCurrentStep(); } case Step::VolumeCreatedInfo: Creator.reset(); SetCancelButtonText (L""); return Step::VolumeHostType; case Step::OuterVolumeContents: try { // Determine maximum size of the hidden volume. Scan cluster table offline as a live filesystem test would // require using FUSE and loop device which cannot be used for devices with sectors larger than 512. wxBusyCursor busy; MaxHiddenVolumeSize = 0; Gui->SetActiveFrame (this); if (MountedOuterVolume) { Core->DismountVolume (MountedOuterVolume); MountedOuterVolume.reset(); } #ifdef TC_UNIX // Temporarily take ownership of a device if the user is not an administrator UserId origDeviceOwner ((uid_t) -1); if (!Core->HasAdminPrivileges() && SelectedVolumePath.IsDevice()) { origDeviceOwner = FilesystemPath (wstring (SelectedVolumePath)).GetOwner(); Core->SetFileOwner (SelectedVolumePath, UserId (getuid())); } finally_do_arg2 (FilesystemPath, SelectedVolumePath, UserId, origDeviceOwner, { if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); }); #endif shared_ptr outerVolume = Core->OpenVolume (make_shared (SelectedVolumePath), true, Password, Pim, Kdf, false, Keyfiles, VolumeProtection::ReadOnly); MaxHiddenVolumeSize = Core->GetMaxHiddenVolumeSize (outerVolume); // Add a reserve (in case the user mounts the outer volume and creates new files // on it by accident or OS writes some new data behind his or her back, such as // System Restore etc.) uint64 reservedSize = outerVolume->GetSize() / 200; if (reservedSize > 10 * BYTES_PER_MB) reservedSize = 10 * BYTES_PER_MB; if (MaxHiddenVolumeSize < reservedSize) MaxHiddenVolumeSize = 0; else MaxHiddenVolumeSize -= reservedSize; MaxHiddenVolumeSize -= MaxHiddenVolumeSize % outerVolume->GetSectorSize(); // Must be a multiple of the sector size } catch (exception &e) { Gui->SetActiveFrame (this); Gui->ShowError (e); return GetCurrentStep(); } return Step::HiddenVolume; case Step::HiddenVolume: return Step::EncryptionOptions; default: throw ParameterIncorrect (SRC_POS); } } void VolumeCreationWizard::UpdateControls () { VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); if (page) { page->EnableAbort (IsWorkInProgress()); } } bool VolumeCreationWizard::DeviceWarningConfirmed; }