📄 bootencryption.cpp
字号:
DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
throw ParameterIncorrect (SRC_POS);
byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
mputInt64 (fieldPos, volumeSize);
EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
VolumeHeaderValid = true;
RescueVolumeHeaderValid = true;
}
void BootEncryption::InstallVolumeHeader ()
{
if (!VolumeHeaderValid)
throw ParameterIncorrect (SRC_POS);
Device device (GetSystemDriveConfiguration().DevicePath);
device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader));
}
// For synchronous operations use AbortSetupWait()
void BootEncryption::AbortSetup ()
{
CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
}
// For asynchronous operations use AbortSetup()
void BootEncryption::AbortSetupWait ()
{
CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
BootEncryptionStatus encStatus = GetStatus();
while (encStatus.SetupInProgress)
{
Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL);
encStatus = GetStatus();
}
}
void BootEncryption::BackupSystemLoader ()
{
Device device (GetSystemDriveConfiguration().DevicePath, true);
byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
device.SeekAt (0);
device.Read (bootLoaderBuf, sizeof (bootLoaderBuf));
// Prevent TrueCrypt loader from being backed up
for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i)
{
if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
{
if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO)
throw UserAbort (SRC_POS);
return;
}
}
File backupFile (GetSystemLoaderBackupPath(), false, true);
backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
}
void BootEncryption::RestoreSystemLoader ()
{
byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
File backupFile (GetSystemLoaderBackupPath(), true);
if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf))
throw ParameterIncorrect (SRC_POS);
Device device (GetSystemDriveConfiguration().DevicePath);
device.SeekAt (0);
device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
}
#endif // SETUP
void BootEncryption::RegisterFilterDriver (bool registerDriver)
{
if (!IsAdmin() && IsUacSupported())
{
Elevator::RegisterFilterDriver (registerDriver);
return;
}
HKEY classRegKey = SetupDiOpenClassRegKey (&GUID_DEVCLASS_DISKDRIVE, KEY_READ | KEY_WRITE);
throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
if (registerDriver && nCurrentOS == WIN_VISTA_OR_LATER)
{
// Attaching to the device stack after PartMgr on Vista causes all write IRPs sent to the lower device object to fail
// with STATUS_ACCESS_DENIED. Therefore, our filter is placed in front of others already registered.
size_t strSize = strlen ("truecrypt") + 1;
byte regKeyBuf[65536];
DWORD size = sizeof (regKeyBuf) - strSize;
// SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly
strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf));
if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS)
size = 1;
throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS);
}
else
{
char tempPath[MAX_PATH];
GetTempPath (sizeof (tempPath), tempPath);
string infFileName = string (tempPath) + "\\truecrypt_filter.inf";
finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
File infFile (infFileName, false, true);
string infTxt = "[truecrypt]\r\n" + string (registerDriver ? "Add" : "Del") + "Reg=truecrypt_reg\r\n\r\n"
"[truecrypt_reg]\r\nHKR,,\"UpperFilters\",0x0001" + string (registerDriver ? "0008" : "8002") + ",\"truecrypt\"\r\n";
infFile.Write ((byte *) infTxt.c_str(), infTxt.size());
infFile.Close();
HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
throw_sys_if (hInf == INVALID_HANDLE_VALUE);
finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL));
}
}
#ifndef SETUP
void BootEncryption::CheckRequirements ()
{
if (nCurrentOS == WIN_2000)
throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS");
if (IsNonInstallMode())
throw ErrorException ("FEATURE_REQUIRES_INSTALLATION");
SystemDriveConfiguration config = GetSystemDriveConfiguration ();
if (config.SystemPartition.IsGPT)
throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED");
if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE)
throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER");
DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber);
if (geometry.BytesPerSector != SECTOR_SIZE)
throw ErrorException ("LARGE_SECTOR_UNSUPPORTED");
if (!config.SystemLoaderPresent)
throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
}
void BootEncryption::Deinstall ()
{
BootEncryptionStatus encStatus = GetStatus();
if (encStatus.DriveEncrypted || encStatus.DriveMounted)
throw ParameterIncorrect (SRC_POS);
SystemDriveConfiguration config = GetSystemDriveConfiguration ();
if (encStatus.VolumeHeaderPresent)
{
// Verify CRC of header salt
Device device (config.DevicePath, true);
byte header[SECTOR_SIZE];
device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
device.Read (header, sizeof (header));
if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE))
throw ParameterIncorrect (SRC_POS);
}
RegisterFilterDriver (false);
SetDriverServiceStartType (SERVICE_SYSTEM_START);
try
{
RestoreSystemLoader ();
}
catch (Exception &e)
{
e.Show (ParentWindow);
throw ErrorException ("SYS_LOADER_RESTORE_FAILED");
}
}
int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5)
{
if (GetStatus().SetupInProgress)
throw ParameterIncorrect (SRC_POS);
SystemDriveConfiguration config = GetSystemDriveConfiguration ();
char header[HEADER_SIZE];
Device device (config.DevicePath);
// Only one algorithm is currently supported
if (pkcs5 != 0)
throw ParameterIncorrect (SRC_POS);
device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
device.Read ((byte *) header, sizeof (header));
PCRYPTO_INFO cryptoInfo = NULL;
int status = VolumeReadHeader (TRUE, header, oldPassword, &cryptoInfo, NULL);
finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
if (status != 0)
{
handleError (ParentWindow, status);
return status;
}
// Change the PKCS-5 PRF if requested by user
if (pkcs5 != 0)
cryptoInfo->pkcs5 = pkcs5;
throw_sys_if (Randinit () != 0);
/* The header will be re-encrypted PRAND_DISK_WIPE_PASSES 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. */
bool headerUpdated = false;
int result = ERR_SUCCESS;
try
{
for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
{
PCRYPTO_INFO tmpCryptoInfo = NULL;
status = VolumeWriteHeader (TRUE,
header,
cryptoInfo->ea,
cryptoInfo->mode,
newPassword,
cryptoInfo->pkcs5,
(char *) cryptoInfo->master_keydata,
cryptoInfo->volume_creation_time,
&tmpCryptoInfo,
cryptoInfo->VolumeSize.Value,
cryptoInfo->hiddenVolumeSize,
cryptoInfo->EncryptedAreaStart.Value,
cryptoInfo->EncryptedAreaLength.Value,
wipePass < PRAND_DISK_WIPE_PASSES - 1);
if (tmpCryptoInfo)
crypto_close (tmpCryptoInfo);
if (status != 0)
{
handleError (ParentWindow, status);
return status;
}
device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
device.Write ((byte *) header, sizeof (header));
headerUpdated = true;
}
}
catch (Exception &e)
{
e.Show (ParentWindow);
result = ERR_OS_ERROR;
}
if (headerUpdated)
{
ReopenBootVolumeHeaderRequest reopenRequest;
reopenRequest.VolumePassword = *newPassword;
finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); });
CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
}
return result;
}
void BootEncryption::CheckEncryptionSetupResult ()
{
CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
}
void BootEncryption::Install ()
{
BootEncryptionStatus encStatus = GetStatus();
if (encStatus.DriveMounted)
throw ParameterIncorrect (SRC_POS);
try
{
InstallBootLoader ();
InstallVolumeHeader ();
RegisterBootDriver ();
// Prevent system log errors caused by rejecting crash dumps
WriteLocalMachineRegistryDword ("System\\CurrentControlSet\\Control\\CrashControl", "CrashDumpEnabled", 0);
}
catch (Exception &)
{
try
{
RestoreSystemLoader ();
}
catch (Exception &e)
{
e.Show (ParentWindow);
}
throw;
}
}
void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath)
{
if (!systemPartitionOnly && !RealSystemDriveSizeValid)
ProbeRealSystemDriveSize();
BootEncryptionStatus encStatus = GetStatus();
if (encStatus.DriveMounted)
throw ParameterIncorrect (SRC_POS);
CheckRequirements ();
SystemDriveConfiguration config = GetSystemDriveConfiguration();
BackupSystemLoader ();
uint64 volumeSize;
uint64 encryptedAreaStart;
if (systemPartitionOnly)
{
volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart;
encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart;
}
else
{
volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE;
encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE;
}
SelectedEncryptionAlgorithmId = ea;
CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5);
if (!rescueIsoImagePath.empty())
CreateRescueIsoImage (true, rescueIsoImagePath);
}
void BootEncryption::StartDecryption ()
{
BootEncryptionStatus encStatus = GetStatus();
if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
throw ParameterIncorrect (SRC_POS);
BootEncryptionSetupRequest request;
ZeroMemory (&request, sizeof (request));
request.SetupMode = SetupDecryption;
CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
}
void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm)
{
BootEncryptionStatus encStatus = GetStatus();
if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
throw ParameterIncorrect (SRC_POS);
BootEncryptionSetupRequest request;
ZeroMemory (&request, sizeof (request));
request.SetupMode = SetupEncryption;
request.WipeAlgorithm = wipeAlgorithm;
CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
}
#endif // !SETUP
void BootEncryption::RegisterBootDriver (void)
{
SetDriverServiceStartType (SERVICE_BOOT_START);
try
{
RegisterFilterDriver (false);
}
catch (...) { }
RegisterFilterDriver (true);
}
bool BootEncryption::RestartComputer (void)
{
TOKEN_PRIVILEGES tokenPrivil;
HANDLE hTkn;
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn))
{
return false;
}
LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid);
tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tokenPrivil.PrivilegeCount = 1;
AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
return false;
if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE,
SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
return false;
return true;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -