📄 inplace.c
字号:
nStatus = ConcealNTFS (dev);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
// /* If a drive letter is assigned to the device, remove it (so that users do not try to open it, which
//would cause Windows to ask them if they want to format the volume and other dangerous things). */
//if (driveLetter >= 0)
//{
// char rootPath[] = { driveLetter + 'A', ':', '\\', 0 };
// // Try to remove the assigned drive letter
// if (DeleteVolumeMountPoint (rootPath))
// driveLetter = -1;
//}
/* Update config files and app data */
// In the config file, increase the number of partitions where in-place encryption is in progress
SaveNonSysInPlaceEncSettings (1, wipeAlgorithm);
// Add the wizard to the system startup sequence if appropriate
if (!IsNonInstallMode ())
ManageStartupSeqWiz (FALSE, "/prinplace");
nStatus = ERR_SUCCESS;
closing_seq:
dwError = GetLastError();
if (cryptoInfo != NULL)
{
crypto_close (cryptoInfo);
cryptoInfo = NULL;
}
if (cryptoInfo2 != NULL)
{
crypto_close (cryptoInfo2);
cryptoInfo2 = NULL;
}
burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
TCfree (header);
if (dosDev[0])
RemoveFakeDosName (volParams->volumePath, dosDev);
*outHandle = dev;
if (nStatus != ERR_SUCCESS)
SetLastError (dwError);
return nStatus;
}
int EncryptPartitionInPlaceResume (HANDLE dev,
volatile FORMAT_VOL_PARAMETERS *volParams,
WipeAlgorithmId wipeAlgorithm,
volatile BOOL *bTryToCorrectReadErrors)
{
PCRYPTO_INFO masterCryptoInfo = NULL, headerCryptoInfo = NULL, tmpCryptoInfo = NULL;
UINT64_STRUCT unitNo;
char *buf = NULL, *header = NULL;
byte *wipeBuffer = NULL;
byte wipeRandChars [TC_WIPE_RAND_CHAR_COUNT];
byte wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT];
char dosDev[TC_MAX_PATH] = {0};
char devName[MAX_PATH] = {0};
WCHAR deviceName[MAX_PATH];
int nStatus = ERR_SUCCESS;
__int64 deviceSize;
uint64 remainingBytes, lastHeaderUpdateDistance = 0, zeroedSectorCount = 0;
uint32 workChunkSize;
DWORD dwError, dwResult;
BOOL bPause = FALSE, bEncryptedAreaSizeChanged = FALSE;
LARGE_INTEGER offset;
int sectorSize;
int i;
DWORD n;
char *devicePath = volParams->volumePath;
Password *password = volParams->password;
DISK_GEOMETRY driveGeometry;
bInPlaceEncNonSysResumed = TRUE;
buf = (char *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
if (!buf)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
if (!header)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
if (wipeAlgorithm != TC_WIPE_NONE)
{
wipeBuffer = (byte *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
if (!wipeBuffer)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
}
headerCryptoInfo = crypto_open();
if (headerCryptoInfo == NULL)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
deviceSize = GetDeviceSize (devicePath);
if (deviceSize < 0)
{
// Cannot determine the size of the partition
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (dev == INVALID_HANDLE_VALUE)
{
strcpy ((char *)deviceName, devicePath);
ToUNICODE ((char *)deviceName);
if (FakeDosNameForDevice (devicePath, dosDev, devName, FALSE) != 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
dev = OpenPartitionVolume (devName,
FALSE, // Do not require exclusive access
FALSE, // Do not require shared access
TRUE, // Ask the user to confirm shared access (if exclusive fails)
FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages)
FALSE); // Non-silent mode
if (dev == INVALID_HANDLE_VALUE)
{
nStatus = ERR_DONT_REPORT;
goto closing_seq;
}
}
// This should never be needed, but is still performed for extra safety (without checking the result)
DeviceIoControl (dev,
FSCTL_ALLOW_EXTENDED_DASD_IO,
NULL,
0,
NULL,
0,
&dwResult,
NULL);
if (!DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveGeometry, sizeof (driveGeometry), &dwResult, NULL))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
sectorSize = driveGeometry.BytesPerSector;
nStatus = OpenBackupHeader (dev, devicePath, password, &masterCryptoInfo, headerCryptoInfo, deviceSize);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
remainingBytes = masterCryptoInfo->VolumeSize.Value - masterCryptoInfo->EncryptedAreaLength.Value;
lastHeaderUpdateDistance = 0;
ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE);
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ENCRYPTING);
bFirstNonSysInPlaceEncResumeDone = TRUE;
/* The in-place encryption core */
while (remainingBytes > 0)
{
workChunkSize = (uint32) min (remainingBytes, TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
if (workChunkSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
{
nStatus = ERR_PARAMETER_INCORRECT;
goto closing_seq;
}
unitNo.Value = (remainingBytes - workChunkSize + TC_VOLUME_DATA_OFFSET) / ENCRYPTION_DATA_UNIT_SIZE;
// Read the plaintext into RAM
inplace_enc_read:
offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET;
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (ReadFile (dev, buf, workChunkSize, &n, NULL) == 0)
{
// Read error
DWORD dwTmpErr = GetLastError ();
if (dwTmpErr == ERROR_CRC || dwTmpErr == ERROR_IO_DEVICE)
{
// Physical defect or data corruption
if (!*bTryToCorrectReadErrors)
{
*bTryToCorrectReadErrors = (AskWarnYesNo ("ENABLE_BAD_SECTOR_ZEROING") == IDYES);
}
if (*bTryToCorrectReadErrors)
{
// Try to correct the read errors physically
offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET;
nStatus = ZeroUnreadableSectors (dev, offset, workChunkSize, sectorSize, &zeroedSectorCount);
if (nStatus != ERR_SUCCESS)
{
// Due to write errors, we can't correct the read errors
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
goto inplace_enc_read;
}
}
SetLastError (dwTmpErr); // Preserve the original error code
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (remainingBytes - workChunkSize < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE)
{
// We reached the inital portion of the filesystem, which we had concealed (in order to prevent
// Windows from interfering with the volume). Now we need to undo that modification.
for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE - (remainingBytes - workChunkSize); i++)
buf[i] ^= TC_NTFS_CONCEAL_CONSTANT;
}
// Encrypt the plaintext in RAM
EncryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
// If enabled, wipe the area to which we will write the ciphertext
if (wipeAlgorithm != TC_WIPE_NONE)
{
byte wipePass;
offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize;
for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass)
{
if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize))
{
ULONG i;
for (i = 0; i < workChunkSize; ++i)
{
wipeBuffer[i] = buf[i] + wipePass;
}
EncryptDataUnits (wipeBuffer, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate));
}
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0
|| WriteFile (dev, wipeBuffer, workChunkSize, &n, NULL) == 0)
{
// Write error
dwError = GetLastError();
// Undo failed write operation
if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN))
{
DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL);
}
SetLastError (dwError);
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
}
memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate));
}
// Write the ciphertext
offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize;
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (WriteFile (dev, buf, workChunkSize, &n, NULL) == 0)
{
// Write error
dwError = GetLastError();
// Undo failed write operation
if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN))
{
DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL);
}
SetLastError (dwError);
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
masterCryptoInfo->EncryptedAreaStart.Value -= workChunkSize;
masterCryptoInfo->EncryptedAreaLength.Value += workChunkSize;
remainingBytes -= workChunkSize;
lastHeaderUpdateDistance += workChunkSize;
bEncryptedAreaSizeChanged = TRUE;
if (lastHeaderUpdateDistance >= TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL)
{
nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
lastHeaderUpdateDistance = 0;
}
ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE);
if (bVolTransformThreadCancel)
{
bPause = TRUE;
break;
}
}
nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
if (!bPause)
{
/* The data area has been fully encrypted; create and write the primary volume header */
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINALIZING);
nStatus = CreateVolumeHeaderInMemory (FALSE,
header,
headerCryptoInfo->ea,
headerCryptoInfo->mode,
password,
masterCryptoInfo->pkcs5,
(char *) masterCryptoInfo->master_keydata,
&tmpCryptoInfo,
masterCryptoInfo->VolumeSize.Value,
0,
masterCryptoInfo->EncryptedAreaStart.Value,
masterCryptoInfo->EncryptedAreaLength.Value,
masterCryptoInfo->RequiredProgramVersion,
masterCryptoInfo->HeaderFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC,
FALSE);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
offset.QuadPart = TC_VOLUME_HEADER_OFFSET;
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0
|| WriteFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
// Fill the reserved sectors of the header area with random data
nStatus = WriteRandomDataToReservedHeaderAreas (dev, headerCryptoInfo, masterCryptoInfo->VolumeSize.Value, TRUE, FALSE);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
// Update the configuration files
SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm);
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINISHED);
nStatus = ERR_SUCCESS;
}
else
{
// The process has been paused by the user or aborted by the wizard (e.g. on app exit)
nStatus = ERR_USER_ABORT;
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED);
}
closing_seq:
dwError = GetLastError();
if (bEncryptedAreaSizeChanged
&& dev != INVALID_HANDLE_VALUE
&& masterCryptoInfo != NULL
&& headerCryptoInfo != NULL
&& deviceSize > 0)
{
// Execution of the core loop may have been interrupted due to an error or user action without updating the header
FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
}
if (masterCryptoInfo != NULL)
{
crypto_close (masterCryptoInfo);
masterCryptoInfo = NULL;
}
if (headerCryptoInfo != NULL)
{
crypto_close (headerCryptoInfo);
headerCryptoInfo = NULL;
}
if (tmpCryptoInfo != NULL)
{
crypto_close (tmpCryptoInfo);
tmpCryptoInfo = NULL;
}
if (dosDev[0])
RemoveFakeDosName (devicePath, dosDev);
if (dev != INVALID_HANDLE_VALUE)
{
CloseHandle (dev);
dev = INVALID_HANDLE_VALUE;
}
if (buf != NULL)
TCfree (buf);
if (header != NULL)
{
burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
TCfree (header);
}
if (wipeBuffer != NULL)
TCfree (wipeBuffer);
if (zeroedSectorCount > 0)
{
wchar_t msg[30000] = {0};
wchar_t sizeStr[500] = {0};
GetSizeString (zeroedSectorCount * sectorSize, sizeStr);
wsprintfW (msg,
GetString ("ZEROED_BAD_SECTOR_COUNT"),
zeroedSectorCount,
sizeStr);
WarningDirect (msg);
}
if (nStatus != ERR_SUCCESS && nStatus != ERR_USER_ABORT)
SetLastError (dwError);
return nStatus;
}
int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize)
{
LARGE_INTEGER offset;
DWORD n;
int nStatus = ERR_SUCCESS;
byte *header;
DWORD dwError;
uint32 headerCrc32;
byte *fieldPos;
header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
if (!header)
return ERR_OUTOFMEMORY;
VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
fieldPos = (byte *) header + TC_HEADER_OFFSET_ENCRYPTED_AREA_START;
offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE;
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0
|| ReadFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -