📄 tcformat.c
字号:
/*
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-2008 TrueCrypt Foundation and are governed
by the TrueCrypt License 2.6 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 <stdlib.h>
#include <limits.h>
#include <time.h>
#include <errno.h>
#include <io.h>
#include <sys/stat.h>
#include <shlobj.h>
#include "Crypto.h"
#include "Apidrvr.h"
#include "Dlgcode.h"
#include "Language.h"
#include "Combo.h"
#include "Registry.h"
#include "Boot/Windows/BootDefs.h"
#include "Common/Common.h"
#include "Common/BootEncryption.h"
#include "Common/Dictionary.h"
#include "Common/Endian.h"
#include "Common/resource.h"
#include "Platform/Finally.h"
#include "Platform/ForEach.h"
#include "Random.h"
#include "Fat.h"
#include "InPlace.h"
#include "Resource.h"
#include "TcFormat.h"
#include "Format.h"
#include "FormatCom.h"
#include "Password.h"
#include "Progress.h"
#include "Tests.h"
#include "Cmdline.h"
#include "Volumes.h"
#include "Wipe.h"
#include "Xml.h"
using namespace TrueCrypt;
enum wizard_pages
{
/* IMPORTANT: IF YOU ADD/REMOVE/MOVE ANY PAGES THAT ARE RELATED TO SYSTEM ENCRYPTION,
REVISE THE 'DECOY_OS_INSTRUCTIONS' STRING! */
INTRO_PAGE,
SYSENC_TYPE_PAGE,
SYSENC_HIDDEN_OS_REQ_CHECK_PAGE,
SYSENC_SPAN_PAGE,
SYSENC_PRE_DRIVE_ANALYSIS_PAGE,
SYSENC_DRIVE_ANALYSIS_PAGE,
SYSENC_MULTI_BOOT_MODE_PAGE,
SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE,
SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE,
SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE,
SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE,
SYSENC_MULTI_BOOT_OUTCOME_PAGE,
VOLUME_TYPE_PAGE,
HIDDEN_VOL_WIZARD_MODE_PAGE,
VOLUME_LOCATION_PAGE,
DEVICE_TRANSFORM_MODE_PAGE,
HIDDEN_VOL_HOST_PRE_CIPHER_PAGE,
HIDDEN_VOL_PRE_CIPHER_PAGE,
CIPHER_PAGE,
SIZE_PAGE,
HIDDEN_VOL_HOST_PASSWORD_PAGE,
PASSWORD_PAGE,
FILESYS_PAGE,
SYSENC_COLLECTING_RANDOM_DATA_PAGE,
SYSENC_KEYS_GEN_PAGE,
SYSENC_RESCUE_DISK_CREATION_PAGE,
SYSENC_RESCUE_DISK_BURN_PAGE,
SYSENC_RESCUE_DISK_VERIFIED_PAGE,
SYSENC_WIPE_MODE_PAGE,
SYSENC_PRETEST_INFO_PAGE,
SYSENC_PRETEST_RESULT_PAGE,
SYSENC_ENCRYPTION_PAGE,
NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE,
NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE,
NONSYS_INPLACE_ENC_RAND_DATA_PAGE,
NONSYS_INPLACE_ENC_WIPE_MODE_PAGE,
NONSYS_INPLACE_ENC_ENCRYPTION_PAGE,
NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE,
FORMAT_PAGE,
FORMAT_FINISHED_PAGE,
SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE,
SYSENC_HIDDEN_OS_WIPE_INFO_PAGE,
DEVICE_WIPE_MODE_PAGE,
DEVICE_WIPE_PAGE
};
#define TIMER_INTERVAL_RANDVIEW 30
#define TIMER_INTERVAL_SYSENC_PROGRESS 30
#define TIMER_INTERVAL_NONSYS_INPLACE_ENC_PROGRESS 30
#define TIMER_INTERVAL_SYSENC_DRIVE_ANALYSIS_PROGRESS 100
#define TIMER_INTERVAL_WIPE_PROGRESS 30
#define TIMER_INTERVAL_KEYB_LAYOUT_GUARD 10
enum sys_encryption_cmd_line_switches
{
SYSENC_COMMAND_NONE = 0,
SYSENC_COMMAND_RESUME,
SYSENC_COMMAND_STARTUP_SEQ_RESUME,
SYSENC_COMMAND_ENCRYPT,
SYSENC_COMMAND_DECRYPT,
SYSENC_COMMAND_CREATE_HIDDEN_OS,
SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV
};
typedef struct
{
int NumberOfSysDrives; // Number of drives that contain an operating system. -1: unknown, 1: one, 2: two or more
int MultipleSystemsOnDrive; // Multiple systems are installed on the drive where the currently running system resides. -1: unknown, 0: no, 1: yes
int BootLoaderLocation; // Boot loader (boot manager) installed in: 1: MBR/1st cylinder, 0: partition/bootsector: -1: unknown
int BootLoaderBrand; // -1: unknown, 0: Microsoft Windows, 1: any non-Windows boot manager/loader
int SystemOnBootDrive; // If the currently running operating system is installed on the boot drive. -1: unknown, 0: no, 1: yes
} SYSENC_MULTIBOOT_CFG;
#define SYSENC_PAUSE_RETRY_INTERVAL 100
#define SYSENC_PAUSE_RETRIES 200
// Expected duration of system drive analysis, in ms
#define SYSENC_DRIVE_ANALYSIS_ETA (4*60000)
BootEncryption *BootEncObj = NULL;
BootEncryptionStatus BootEncStatus;
HWND hCurPage = NULL; /* Handle to current wizard page */
int nCurPageNo = -1; /* The current wizard page */
int nLastPageNo = -1;
volatile int WizardMode = DEFAULT_VOL_CREATION_WIZARD_MODE; /* IMPORTANT: Never change this value directly -- always use ChangeWizardMode() instead. */
volatile BOOL bHiddenOS = FALSE; /* If TRUE, we are performing or (or supposed to perform) actions relating to an operating system installed in a hidden volume (i.e., encrypting a decoy OS partition or creating the outer/hidden volume for the hidden OS). To determine or set the phase of the process, call ChangeHiddenOSCreationPhase() and DetermineHiddenOSCreationPhase()) */
BOOL bDirectSysEncMode = FALSE;
BOOL bDirectSysEncModeCommand = SYSENC_COMMAND_NONE;
BOOL DirectDeviceEncMode = FALSE;
BOOL DirectNonSysInplaceEncResumeMode = FALSE;
BOOL DirectPromptNonSysInplaceEncResumeMode = FALSE;
volatile BOOL bInPlaceEncNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be encrypted (for system encryption, this flag is ignored) */
volatile BOOL bInPlaceEncNonSysResumed = FALSE; /* If TRUE, the wizard is supposed to resume (or has resumed) process of non-system in-place encryption. */
volatile BOOL bFirstNonSysInPlaceEncResumeDone = FALSE;
__int64 NonSysInplaceEncBytesDone = 0;
__int64 NonSysInplaceEncTotalSectors = 0;
BOOL bDeviceTransformModeChoiceMade = FALSE; /* TRUE if the user has at least once manually selected the 'in-place' or 'format' option (on the 'device transform mode' page). */
int nNeedToStoreFilesOver4GB = 0; /* Whether the user wants to be able to store files larger than 4GB on the volume: -1 = Undecided or error, 0 = No, 1 = Yes */
int nVolumeEA = 1; /* Default encryption algorithm */
BOOL bSystemEncryptionInProgress = FALSE; /* TRUE when encrypting/decrypting the system partition/drive (FALSE when paused). */
BOOL bWholeSysDrive = FALSE; /* Whether to encrypt the entire system drive or just the system partition. */
static BOOL bSystemEncryptionStatusChanged = FALSE; /* TRUE if this instance changed the value of SystemEncryptionStatus (it's set to FALSE each time the system encryption settings are saved to the config file). This value is to be treated as protected -- only the wizard can change this value (others may only read it). */
volatile BOOL bSysEncDriveAnalysisInProgress = FALSE;
volatile BOOL bSysEncDriveAnalysisTimeOutOccurred = FALSE;
int SysEncDetectHiddenSectors = -1; /* Whether the user wants us to detect and encrypt the Host Protect Area (if any): -1 = Undecided or error, 0 = No, 1 = Yes */
int SysEncDriveAnalysisStart;
BOOL bDontVerifyRescueDisk = FALSE;
BOOL bFirstSysEncResumeDone = FALSE;
int nMultiBoot = 0; /* The number of operating systems installed on the computer, according to the user. 0: undetermined, 1: one, 2: two or more */
volatile BOOL bHiddenVol = FALSE; /* If true, we are (or will be) creating a hidden volume. */
volatile BOOL bHiddenVolHost = FALSE; /* If true, we are (or will be) creating the host volume (called "outer") for a hidden volume. */
volatile BOOL bHiddenVolDirect = FALSE; /* If true, the wizard omits creating a host volume in the course of the process of hidden volume creation. */
volatile BOOL bHiddenVolFinished = FALSE;
int hiddenVolHostDriveNo = -1; /* Drive letter for the volume intended to host a hidden volume. */
BOOL bRemovableHostDevice = FALSE; /* TRUE when creating a device/partition-hosted volume on a removable device. State undefined when creating file-hosted volumes. */
int realClusterSize; /* Parameter used when determining the maximum possible size of a hidden volume. */
int hash_algo = DEFAULT_HASH_ALGORITHM; /* Which PRF to use in header key derivation (PKCS #5) and in the RNG. */
unsigned __int64 nUIVolumeSize = 0; /* The volume size. Important: This value is not in bytes. It has to be multiplied by nMultiplier. Do not use this value when actually creating the volume (it may chop off 512 bytes, if it is not a multiple of 1024 bytes). */
unsigned __int64 nVolumeSize = 0; /* The volume size, in bytes. */
unsigned __int64 nHiddenVolHostSize = 0; /* Size of the hidden volume host, in bytes */
__int64 nMaximumHiddenVolSize = 0; /* Maximum possible size of the hidden volume, in bytes */
__int64 nbrFreeClusters = 0;
int nMultiplier = BYTES_PER_MB; /* Size selection multiplier. */
char szFileName[TC_MAX_PATH+1]; /* The file selected by the user */
char szDiskFile[TC_MAX_PATH+1]; /* Fully qualified name derived from szFileName */
char szRescueDiskISO[TC_MAX_PATH+1]; /* The filename and path to the Rescue Disk ISO file to be burned (for boot encryption) */
BOOL bDeviceWipeInProgress = FALSE;
volatile BOOL bTryToCorrectReadErrors = FALSE;
volatile BOOL bVolTransformThreadCancel = FALSE; /* TRUE if the user cancels/pauses volume encryption/format */
volatile BOOL bVolTransformThreadRunning = FALSE; /* Is the volume encryption/format thread running */
volatile BOOL bVolTransformThreadToRun = FALSE; /* TRUE if the Format/Encrypt button has been clicked and we are proceeding towards launching the thread. */
volatile BOOL bConfirmQuit = FALSE; /* If TRUE, the user is asked to confirm exit when he clicks the X icon, Exit, etc. */
volatile BOOL bConfirmQuitSysEncPretest = FALSE;
BOOL bDevice = FALSE; /* Is this a partition volume ? */
BOOL showKeys = TRUE;
volatile HWND hMasterKey = NULL; /* Text box showing hex dump of the master key */
volatile HWND hHeaderKey = NULL; /* Text box showing hex dump of the header key */
volatile HWND hRandPool = NULL; /* Text box showing hex dump of the random pool */
volatile HWND hRandPoolSys = NULL; /* Text box showing hex dump of the random pool for system encryption */
volatile HWND hPasswordInputField = NULL; /* Password input field */
volatile HWND hVerifyPasswordInputField = NULL; /* Verify-password input field */
HBITMAP hbmWizardBitmapRescaled = NULL;
char OrigKeyboardLayout [8+1] = "00000409";
BOOL bKeyboardLayoutChanged = FALSE; /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */
BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */
#ifndef _DEBUG
BOOL bWarnDeviceFormatAdvanced = TRUE;
#else
BOOL bWarnDeviceFormatAdvanced = FALSE;
#endif
BOOL bWarnOuterVolSuitableFileSys = TRUE;
Password volumePassword; /* User password */
char szVerify[MAX_PASSWORD + 1]; /* Tmp password buffer */
char szRawPassword[MAX_PASSWORD + 1]; /* Password before keyfile was applied to it */
BOOL bHistoryCmdLine = FALSE; /* History control is always disabled */
BOOL ComServerMode = FALSE;
int nPbar = 0; /* Control ID of progress bar:- for format code */
char HeaderKeyGUIView [KEY_GUI_VIEW_SIZE];
char MasterKeyGUIView [KEY_GUI_VIEW_SIZE];
#define RANDPOOL_DISPLAY_COLUMNS 15
#define RANDPOOL_DISPLAY_ROWS 8
#define RANDPOOL_DISPLAY_BYTE_PORTION (RANDPOOL_DISPLAY_COLUMNS * RANDPOOL_DISPLAY_ROWS)
#define RANDPOOL_DISPLAY_SIZE (RANDPOOL_DISPLAY_BYTE_PORTION * 3 + RANDPOOL_DISPLAY_ROWS + 2)
unsigned char randPool [RANDPOOL_DISPLAY_BYTE_PORTION];
unsigned char lastRandPool [RANDPOOL_DISPLAY_BYTE_PORTION];
unsigned char outRandPoolDispBuffer [RANDPOOL_DISPLAY_SIZE];
BOOL bDisplayPoolContents = TRUE;
volatile BOOL bSparseFileSwitch = FALSE;
volatile BOOL quickFormat = FALSE; /* WARNING: Meaning of this variable depends on bSparseFileSwitch. If bSparseFileSwitch is TRUE, this variable represents the sparse file flag. */
volatile int fileSystem = FILESYS_NONE;
volatile int clusterSize = 0;
SYSENC_MULTIBOOT_CFG SysEncMultiBootCfg;
wchar_t SysEncMultiBootCfgOutcome [4096] = {'N','/','A',0};
volatile int NonSysInplaceEncStatus = NONSYS_INPLACE_ENC_STATUS_NONE;
vector <HostDevice> DeferredNonSysInPlaceEncDevices;
static BOOL ElevateWholeWizardProcess (string arguments)
{
char modPath[MAX_PATH];
if (IsAdmin())
return TRUE;
if (!IsUacSupported())
return IsAdmin();
GetModuleFileName (NULL, modPath, sizeof (modPath));
if ((int)ShellExecute (MainDlg, "runas", modPath, (string("/q UAC ") + arguments).c_str(), NULL, SW_SHOWNORMAL) > 32)
{
exit (0);
}
else
{
Error ("UAC_INIT_ERROR");
return FALSE;
}
}
static void WipePasswordsAndKeyfiles (void)
{
char tmp[MAX_PASSWORD+1];
// Attempt to wipe passwords stored in the input field buffers
memset (tmp, 'X', MAX_PASSWORD);
tmp [MAX_PASSWORD] = 0;
SetWindowText (hPasswordInputField, tmp);
SetWindowText (hVerifyPasswordInputField, tmp);
burn (&szVerify[0], sizeof (szVerify));
burn (&volumePassword, sizeof (volumePassword));
burn (&szRawPassword[0], sizeof (szRawPassword));
SetWindowText (hPasswordInputField, "");
SetWindowText (hVerifyPasswordInputField, "");
KeyFileRemoveAll (&FirstKeyFile);
KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile);
}
static void localcleanup (void)
{
char tmp[RANDPOOL_DISPLAY_SIZE+1];
// System encryption
if (WizardMode == WIZARD_MODE_SYS_DEVICE
&& InstanceHasSysEncMutex ())
{
try
{
BootEncStatus = BootEncObj->GetStatus();
if (BootEncStatus.SetupInProgress)
{
BootEncObj->AbortSetup ();
}
}
catch (...)
{
// NOP
}
}
// Mon-system in-place encryption
if (bInPlaceEncNonSys && (bVolTransformThreadRunning || bVolTransformThreadToRun))
{
NonSysInplaceEncPause ();
}
CloseNonSysInplaceEncMutex ();
// Device wipe
if (bDeviceWipeInProgress)
WipeAbort();
WipePasswordsAndKeyfiles ();
Randfree ();
burn (HeaderKeyGUIView, sizeof(HeaderKeyGUIView));
burn (MasterKeyGUIView, sizeof(MasterKeyGUIView));
burn (randPool, sizeof(randPool));
burn (lastRandPool, sizeof(lastRandPool));
burn (outRandPoolDispBuffer, sizeof(outRandPoolDispBuffer));
burn (szFileName, sizeof(szFileName));
burn (szDiskFile, sizeof(szDiskFile));
// Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys
memset (tmp, 'X', sizeof(tmp));
tmp [sizeof(tmp)-1] = 0;
SetWindowText (hRandPool, tmp);
SetWindowText (hRandPoolSys, tmp);
SetWindowText (hMasterKey, tmp);
SetWindowText (hHeaderKey, tmp);
UnregisterRedTick (hInst);
// Delete buffered bitmaps (if any)
if (hbmWizardBitmapRescaled != NULL)
{
DeleteObject ((HGDIOBJ) hbmWizardBitmapRescaled);
hbmWizardBitmapRescaled = NULL;
}
// Cleanup common code resources
cleanup ();
if (BootEncObj != NULL)
{
delete BootEncObj;
BootEncObj = NULL;
}
}
static BOOL CALLBACK BroadcastSysEncCfgUpdateCallb (HWND hwnd, LPARAM lParam)
{
if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE')
{
char name[1024] = { 0 };
GetWindowText (hwnd, name, sizeof (name) - 1);
if (hwnd != MainDlg && strstr (name, "TrueCrypt"))
{
PostMessage (hwnd, TC_APPMSG_SYSENC_CONFIG_UPDATE, 0, 0);
}
}
return TRUE;
}
static BOOL BroadcastSysEncCfgUpdate (void)
{
BOOL bSuccess = FALSE;
EnumWindows (BroadcastSysEncCfgUpdateCallb, (LPARAM) &bSuccess);
return bSuccess;
}
// IMPORTANT: This function may be called only by Format (other modules can only _read_ the system encryption config).
// Returns TRUE if successful (otherwise FALSE)
static BOOL SaveSysEncSettings (HWND hwndDlg)
{
FILE *f;
if (!bSystemEncryptionStatusChanged)
return TRUE;
if (hwndDlg == NULL && MainDlg != NULL)
hwndDlg = MainDlg;
if (!CreateSysEncMutex ())
return FALSE; // Only one instance that has the mutex can modify the system encryption settings
if (SystemEncryptionStatus == SYSENC_STATUS_NONE)
{
if (remove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION)) != 0)
{
Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS");
return FALSE;
}
bSystemEncryptionStatusChanged = FALSE;
BroadcastSysEncCfgUpdate ();
return TRUE;
}
f = fopen (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), "w");
if (f == NULL)
{
Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS");
handleWin32Error (hwndDlg);
return FALSE;
}
if (XmlWriteHeader (f) < 0
|| fputs ("\n\t<sysencryption>", f) < 0
|| fprintf (f, "\n\t\t<config key=\"SystemEncryptionStatus\">%d</config>", SystemEncryptionStatus) < 0
|| fprintf (f, "\n\t\t<config key=\"WipeMode\">%d</config>", (int) nWipeMode) < 0
|| fputs ("\n\t</sysencryption>", f) < 0
|| XmlWriteFooter (f) < 0)
{
handleWin32Error (hwndDlg);
fclose (f);
Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS");
return FALSE;
}
TCFlushFile (f);
fclose (f);
bSystemEncryptionStatusChanged = FALSE;
BroadcastSysEncCfgUpdate ();
return TRUE;
}
// WARNING: This function may take a long time to finish
static unsigned int DetermineHiddenOSCreationPhase (void)
{
unsigned int phase = TC_HIDDEN_OS_CREATION_PHASE_NONE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -