📄 bootencryption.cpp
字号:
device.SeekAt (0);
device.Write (mbr, sizeof (mbr));
byte mbrVerificationBuf[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbrVerificationBuf, sizeof (mbr));
if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
throw ErrorException ("ERROR_MBR_PROTECTED");
}
unsigned int BootEncryption::GetHiddenOSCreationPhase ()
{
byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
ReadBootSectorConfig (configFlags, sizeof(configFlags));
return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE);
}
void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase)
{
#if TC_BOOT_CFG_FLAG_AREA_SIZE != 1
# error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase()
#endif
byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
ReadBootSectorConfig (configFlags, sizeof(configFlags));
configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
configFlags[0] |= newPhase;
WriteBootSectorConfig (configFlags);
}
#ifndef SETUP
void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm)
{
if (!IsHiddenOSRunning())
throw ParameterIncorrect (SRC_POS);
WipeDecoySystemRequest request;
ZeroMemory (&request, sizeof (request));
request.WipeAlgorithm = wipeAlgorithm;
if (Randinit() != ERR_SUCCESS)
throw ParameterIncorrect (SRC_POS);
if (!RandgetBytes (request.WipeKey, sizeof (request.WipeKey), TRUE))
throw ParameterIncorrect (SRC_POS);
CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0);
burn (&request, sizeof (request));
}
void BootEncryption::AbortDecoyOSWipe ()
{
CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE);
}
DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus ()
{
DecoySystemWipeStatus status;
CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status));
return status;
}
void BootEncryption::CheckDecoyOSWipeResult ()
{
CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT);
}
void BootEncryption::WipeHiddenOSCreationConfig ()
{
if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS)
throw ParameterIncorrect (SRC_POS);
Device device (GetSystemDriveConfiguration().DevicePath);
byte mbr[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbr, sizeof (mbr));
finally_do_arg (BootEncryption *, this,
{
try
{
finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
} catch (...) { }
});
#if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
# error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
#endif
byte randData[PRAND_DISK_WIPE_PASSES];
if (!RandgetBytes (randData, sizeof (randData), FALSE))
throw ParameterIncorrect (SRC_POS);
for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
{
for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i)
{
mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass];
}
mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
if (wipePass == PRAND_DISK_WIPE_PASSES - 1)
memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE);
device.SeekAt (0);
device.Write (mbr, sizeof (mbr));
}
for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++)
{
SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING);
SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING);
SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED);
}
SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
}
#endif // !SETUP
void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation)
{
byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE];
CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
// Write MBR
Device device (GetSystemDriveConfiguration().DevicePath);
byte mbr[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbr, sizeof (mbr));
if (preserveUserConfig)
{
uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
if (version != 0)
{
bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
}
}
memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
device.SeekAt (0);
device.Write (mbr, sizeof (mbr));
byte mbrVerificationBuf[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbrVerificationBuf, sizeof (mbr));
if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
throw ErrorException ("ERROR_MBR_PROTECTED");
// Write boot loader
device.SeekAt (SECTOR_SIZE);
device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE);
}
string BootEncryption::GetSystemLoaderBackupPath ()
{
char pathBuf[MAX_PATH];
throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf)));
string path = string (pathBuf) + "\\" TC_APP_NAME;
CreateDirectory (path.c_str(), NULL);
return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME;
}
void BootEncryption::RenameDeprecatedSystemLoaderBackup ()
{
char pathBuf[MAX_PATH];
if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf)))
{
string path = string (pathBuf) + "\\" TC_APP_NAME + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY;
if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str()))
throw_sys_if (rename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0);
}
}
#ifndef SETUP
void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath)
{
BootEncryptionStatus encStatus = GetStatus();
if (encStatus.SetupInProgress)
throw ParameterIncorrect (SRC_POS);
Buffer imageBuf (RescueIsoImageSize);
byte *image = imageBuf.Ptr();
memset (image, 0, RescueIsoImageSize);
// Primary volume descriptor
strcpy ((char *)image + 0x8000, "\001CD001\001");
strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk ");
*(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048;
*(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048);
image[0x7fff + 121] = 1;
image[0x7fff + 124] = 1;
image[0x7fff + 125] = 1;
image[0x7fff + 128] = 1;
image[0x7fff + 130] = 8;
image[0x7fff + 131] = 8;
image[0x7fff + 133] = 10;
image[0x7fff + 140] = 10;
image[0x7fff + 141] = 0x14;
image[0x7fff + 157] = 0x22;
image[0x7fff + 159] = 0x18;
// Boot record volume descriptor
strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION");
image[0x8800 + 0x47] = 0x19;
// Volume descriptor set terminator
strcpy ((char *)image + 0x9000, "\377CD001\001");
// Path table
image[0xA000 + 0] = 1;
image[0xA000 + 2] = 0x18;
image[0xA000 + 6] = 1;
// Root directory
image[0xc000 + 0] = 0x22;
image[0xc000 + 2] = 0x18;
image[0xc000 + 9] = 0x18;
image[0xc000 + 11] = 0x08;
image[0xc000 + 16] = 0x08;
image[0xc000 + 25] = 0x02;
image[0xc000 + 28] = 0x01;
image[0xc000 + 31] = 0x01;
image[0xc000 + 32] = 0x01;
image[0xc000 + 34] = 0x22;
image[0xc000 + 36] = 0x18;
image[0xc000 + 43] = 0x18;
image[0xc000 + 45] = 0x08;
image[0xc000 + 50] = 0x08;
image[0xc000 + 59] = 0x02;
image[0xc000 + 62] = 0x01;
*(uint32 *) (image + 0xc000 + 65) = 0x010101;
// Validation entry
image[0xc800] = 1;
int offset = 0xc800 + 0x1c;
image[offset++] = 0xaa;
image[offset++] = 0x55;
image[offset++] = 0x55;
image[offset] = 0xaa;
// Initial entry
offset = 0xc820;
image[offset++] = 0x88;
image[offset++] = 2;
image[0xc820 + 6] = 1;
image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR;
// TrueCrypt Boot Loader
CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true);
// Volume header
if (initialSetup)
{
if (!RescueVolumeHeaderValid)
throw ParameterIncorrect (SRC_POS);
memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
}
else
{
Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
}
// Original system loader
try
{
File sysBakFile (GetSystemLoaderBackupPath(), true);
sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE);
image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER;
}
catch (Exception &e)
{
e.Show (ParentWindow);
Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK");
}
// Boot loader backup
CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false);
RescueIsoImage = new byte[RescueIsoImageSize];
if (!RescueIsoImage)
throw bad_alloc();
memcpy (RescueIsoImage, image, RescueIsoImageSize);
if (!isoImagePath.empty())
{
File isoFile (isoImagePath, false, true);
isoFile.Write (image, RescueIsoImageSize);
}
}
#endif
bool BootEncryption::VerifyRescueDisk ()
{
if (!RescueIsoImage)
throw ParameterIncorrect (SRC_POS);
for (char drive = 'Z'; drive >= 'D'; --drive)
{
try
{
string path = "X:";
path[0] = drive;
Device driveDevice (path, true);
size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
Buffer buffer ((verifiedSectorCount + 1) * 2048);
DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size());
if (bytesRead != buffer.Size())
continue;
if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
return true;
}
catch (...) { }
}
return false;
}
#ifndef SETUP
void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5)
{
PCRYPTO_INFO cryptoInfo = NULL;
throw_sys_if (Randinit () != 0);
throw_sys_if (CreateVolumeHeaderInMemory (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, &cryptoInfo,
volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, FALSE) != 0);
finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); });
// Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo);
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);
// CRC of the header fields
uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC;
mputLong (fieldPos, crc);
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);
// Preserve current partition table
byte mbr[SECTOR_SIZE];
device.SeekAt (0);
device.Read (mbr, sizeof (mbr));
memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE);
device.SeekAt (0);
device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
}
#endif // SETUP
void BootEncryption::RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid)
{
HKEY classRegKey = SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE);
throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
if (registerFilter)
{
// Register class filter below all other filters in the stack
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
{
// Unregister a class filter
string infFileName = GetTempPath() + "\\truecrypt_device_filter.inf";
File infFile (infFileName, false, true);
finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
string infTxt = "[truecrypt]\r\n"
"DelReg=truecrypt_reg\r\n\r\n"
"[truecrypt_reg]\r\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -