VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Format/InPlace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Format/InPlace.c')
-rw-r--r--src/Format/InPlace.c73
1 files changed, 38 insertions, 35 deletions
diff --git a/src/Format/InPlace.c b/src/Format/InPlace.c
index 877ff7eb..361b8aeb 100644
--- a/src/Format/InPlace.c
+++ b/src/Format/InPlace.c
@@ -573,107 +573,107 @@ int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, vol
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
header,
volParams->ea,
FIRST_MODE_OF_OPERATION_ID,
volParams->password,
volParams->pkcs5,
volParams->pim,
wipePass == 0 ? NULL : (char *) cryptoInfo->master_keydata,
&cryptoInfo,
dataAreaSize,
0,
TC_VOLUME_DATA_OFFSET + dataAreaSize, // Start of the encrypted area = the first byte of the backup heeader (encrypting from the end)
0, // No data is encrypted yet
0,
volParams->headerFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC,
volParams->sectorSize,
wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_HEADER_WIPE_PASSES - 1));
if (nStatus != 0)
goto closing_seq;
offset.QuadPart = TC_VOLUME_DATA_OFFSET + dataAreaSize;
if (!MoveFilePointer (dev, offset))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
// Write the backup header to the partition
- if (!WriteEffectiveVolumeHeader (TRUE, dev, (byte *) header))
+ if (!WriteEffectiveVolumeHeader (TRUE, dev, (uint8 *) header))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
// Fill the reserved sectors of the backup header area with random data
nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, dataAreaSize, FALSE, TRUE);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
// write fake hidden volume header to protect against attacks that use statistical entropy
// analysis to detect presence of hidden volumes
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
header,
volParams->ea,
FIRST_MODE_OF_OPERATION_ID,
NULL,
0,
0,
NULL,
&dummyInfo,
dataAreaSize,
dataAreaSize,
TC_VOLUME_DATA_OFFSET + dataAreaSize, // Start of the encrypted area = the first byte of the backup heeader (encrypting from the end)
dataAreaSize, // No data is encrypted yet
0,
volParams->headerFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC,
volParams->sectorSize,
wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_HEADER_WIPE_PASSES - 1));
if (nStatus != ERR_SUCCESS)
goto closing_seq;
crypto_close (dummyInfo);
offset.QuadPart += TC_HIDDEN_VOLUME_HEADER_OFFSET;
if (!MoveFilePointer (dev, offset))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
// Write the fake hidden backup header to the partition
- if (!WriteEffectiveVolumeHeader (TRUE, dev, (byte *) header))
+ if (!WriteEffectiveVolumeHeader (TRUE, dev, (uint8 *) header))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
}
/* Now we will try to decrypt the backup header to verify it has been correctly written. */
nStatus = OpenBackupHeader (dev, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, &cryptoInfo2, NULL, deviceSize);
if (nStatus != ERR_SUCCESS
|| cryptoInfo->EncryptedAreaStart.Value != cryptoInfo2->EncryptedAreaStart.Value
|| cryptoInfo2->EncryptedAreaStart.Value == 0)
{
if (nStatus == ERR_SUCCESS)
nStatus = ERR_PARAMETER_INCORRECT;
goto closing_seq;
}
// The backup header is valid so we know we should be able to safely resume in-place encryption
// of this partition even if the system/app crashes.
/* Conceal the NTFS filesystem (by performing an easy-to-undo modification). This will prevent Windows
and apps from interfering with the volume until it has been fully encrypted. */
@@ -727,108 +727,108 @@ closing_seq:
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];
+ uint8 *wipeBuffer = NULL;
+ uint8 wipeRandChars [TC_WIPE_RAND_CHAR_COUNT];
+ uint8 wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT];
WCHAR dosDev[TC_MAX_PATH] = {0};
WCHAR 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;
WCHAR *devicePath = volParams->volumePath;
Password *password = volParams->password;
int pkcs5_prf = volParams->pkcs5;
int pim = volParams->pim;
DISK_GEOMETRY driveGeometry;
HWND hwndDlg = volParams->hwndDlg;
#ifdef _WIN64
BOOL bIsRamEncryptionEnabled = IsRamEncryptionEnabled();
#endif
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);
+ wipeBuffer = (uint8 *) 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)
{
StringCchCopyW (deviceName, ARRAYSIZE(deviceName), devicePath);
if (FakeDosNameForDevice (deviceName, dosDev, sizeof(dosDev),devName, sizeof(devName),FALSE) != 0)
{
nStatus = ERR_OS_ERROR;
@@ -947,135 +947,135 @@ inplace_enc_read:
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);
+ EncryptDataUnits ((uint8 *) 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;
+ uint8 wipePass;
int wipePassCount = GetWipePassCount (wipeAlgorithm);
if (wipePassCount <= 0)
{
SetLastError (ERROR_INVALID_PARAMETER);
nStatus = ERR_PARAMETER_INCORRECT;
goto closing_seq;
}
offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize;
for (wipePass = 1; wipePass <= wipePassCount; ++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 (MoveFilePointer (dev, offset) == 0
|| WriteFile (dev, wipeBuffer, workChunkSize, &n, NULL) == 0)
{
// Write error
dwError = GetLastError();
// Undo failed write operation
if (workChunkSize > TC_VOLUME_DATA_OFFSET && MoveFilePointer (dev, offset))
{
- DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
+ DecryptDataUnits ((uint8 *) 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 (MoveFilePointer (dev, offset) == 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 && MoveFilePointer (dev, offset))
{
- DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
+ DecryptDataUnits ((uint8 *) 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);
if (bVolTransformThreadCancel)
@@ -1122,120 +1122,120 @@ inplace_enc_read:
password,
masterCryptoInfo->pkcs5,
pim,
(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,
masterCryptoInfo->SectorSize,
wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_HEADER_WIPE_PASSES - 1));
#ifdef _WIN64
if (bIsRamEncryptionEnabled)
{
masterCryptoInfo = cryptoInfoBackup;
burn (&tmpCI, sizeof (CRYPTO_INFO));
VirtualUnlock (&tmpCI, sizeof(tmpCI));
}
#endif
if (nStatus != ERR_SUCCESS)
goto closing_seq;
offset.QuadPart = TC_VOLUME_HEADER_OFFSET;
if (MoveFilePointer (dev, offset) == 0
- || !WriteEffectiveVolumeHeader (TRUE, dev, (byte *) header))
+ || !WriteEffectiveVolumeHeader (TRUE, dev, (uint8 *) header))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
#ifdef _WIN64
if (bIsRamEncryptionEnabled)
{
VirtualLock (&tmpCI, sizeof(tmpCI));
memcpy (&tmpCI, headerCryptoInfo, sizeof (CRYPTO_INFO));
VcUnprotectKeys (&tmpCI, VcGetEncryptionID (headerCryptoInfo));
cryptoInfoBackup = headerCryptoInfo;
headerCryptoInfo = &tmpCI;
}
#endif
// Fill the reserved sectors of the header area with random data
nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, headerCryptoInfo, masterCryptoInfo->VolumeSize.Value, TRUE, FALSE);
#ifdef _WIN64
if (bIsRamEncryptionEnabled)
{
headerCryptoInfo = cryptoInfoBackup;
burn (&tmpCI, sizeof (CRYPTO_INFO));
VirtualUnlock (&tmpCI, sizeof(tmpCI));
}
#endif
if (nStatus != ERR_SUCCESS)
goto closing_seq;
// write fake hidden volume header to protect against attacks that use statistical entropy
// analysis to detect presence of hidden volumes
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
header,
headerCryptoInfo->ea,
headerCryptoInfo->mode,
NULL,
0,
0,
NULL,
&dummyInfo,
masterCryptoInfo->VolumeSize.Value,
masterCryptoInfo->VolumeSize.Value,
masterCryptoInfo->EncryptedAreaStart.Value,
masterCryptoInfo->EncryptedAreaLength.Value,
masterCryptoInfo->RequiredProgramVersion,
masterCryptoInfo->HeaderFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC,
masterCryptoInfo->SectorSize,
wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_HEADER_WIPE_PASSES - 1));
if (nStatus != ERR_SUCCESS)
goto closing_seq;
crypto_close (dummyInfo);
offset.QuadPart += TC_HIDDEN_VOLUME_HEADER_OFFSET;
if (MoveFilePointer (dev, offset) == 0
- || !WriteEffectiveVolumeHeader (TRUE, dev, (byte *) header))
+ || !WriteEffectiveVolumeHeader (TRUE, dev, (uint8 *) header))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
}
// Update the configuration files
SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm, FALSE);
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();
@@ -1289,61 +1289,61 @@ closing_seq:
if (wipeBuffer != NULL)
TCfree (wipeBuffer);
if (zeroedSectorCount > 0)
{
wchar_t msg[30000] = {0};
wchar_t sizeStr[500] = {0};
GetSizeString (zeroedSectorCount * sectorSize, sizeStr, sizeof(sizeStr));
StringCbPrintfW (msg, sizeof(msg),
GetString ("ZEROED_BAD_SECTOR_COUNT"),
zeroedSectorCount,
sizeStr);
WarningDirect (msg, hwndDlg);
}
if (nStatus != ERR_SUCCESS && nStatus != ERR_USER_ABORT)
SetLastError (dwError);
return nStatus;
}
int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile BOOL *DiscardUnreadableEncryptedSectors)
{
HANDLE dev = INVALID_HANDLE_VALUE;
PCRYPTO_INFO masterCryptoInfo = NULL, headerCryptoInfo = NULL;
UINT64_STRUCT unitNo;
char *buf = NULL;
- byte *tmpSectorBuf = NULL;
+ uint8 *tmpSectorBuf = NULL;
WCHAR dosDev[TC_MAX_PATH] = {0};
WCHAR devName[MAX_PATH] = {0};
WCHAR deviceName[MAX_PATH];
int nStatus = ERR_SUCCESS;
__int64 deviceSize;
uint64 remainingBytes, workChunkStartByteOffset, lastHeaderUpdateDistance = 0, skippedBadSectorCount = 0;
uint32 workChunkSize;
DWORD dwError, dwResult;
BOOL bPause = FALSE, bEncryptedAreaSizeChanged = FALSE;
LARGE_INTEGER offset;
int sectorSize;
int i;
DWORD n;
WCHAR *devicePath = volParams->volumePath;
Password *password = volParams->password;
HWND hwndDlg = volParams->hwndDlg;
int pkcs5_prf = volParams->pkcs5;
int pim = volParams->pim;
DISK_GEOMETRY driveGeometry;
#ifdef _WIN64
BOOL bIsRamEncryptionEnabled = IsRamEncryptionEnabled();
#endif
buf = (char *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
if (!buf)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
@@ -1405,61 +1405,61 @@ int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile
// 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;
}
if ( (driveGeometry.BytesPerSector == 0)
|| (driveGeometry.BytesPerSector > TC_MAX_VOLUME_SECTOR_SIZE)
|| (driveGeometry.BytesPerSector % ENCRYPTION_DATA_UNIT_SIZE != 0)
)
{
Error ("SECTOR_SIZE_UNSUPPORTED", hwndDlg);
nStatus = ERR_DONT_REPORT;
goto closing_seq;
}
sectorSize = driveGeometry.BytesPerSector;
- tmpSectorBuf = (byte *) TCalloc (sectorSize);
+ tmpSectorBuf = (uint8 *) TCalloc (sectorSize);
if (!tmpSectorBuf)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
nStatus = OpenBackupHeader (dev, devicePath, password, pkcs5_prf, pim, &masterCryptoInfo, headerCryptoInfo, deviceSize);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
#ifdef _WIN64
if (bIsRamEncryptionEnabled)
{
VcProtectKeys (masterCryptoInfo, VcGetEncryptionID (masterCryptoInfo));
VcProtectKeys (headerCryptoInfo, VcGetEncryptionID (headerCryptoInfo));
}
#endif
if (masterCryptoInfo->LegacyVolume)
{
Error ("NONSYS_INPLACE_DECRYPTION_BAD_VOL_FORMAT", hwndDlg);
nStatus = ERR_DONT_REPORT;
goto closing_seq;
}
if (masterCryptoInfo->hiddenVolume)
{
Error ("NONSYS_INPLACE_DECRYPTION_CANT_DECRYPT_HID_VOL", hwndDlg);
@@ -1593,61 +1593,61 @@ int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile
memset (tmpSectorBuf, 0, sectorSize);
skippedBadSectorCount++;
}
memcpy (buf + tmpBufOffset, tmpSectorBuf, sectorSize);
tmpSectorOffset.QuadPart += sectorSize;
tmpBufOffset += sectorSize;
}
}
else
{
SetLastError (dwTmpErr); // Preserve the original error code
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
}
else
{
SetLastError (dwTmpErr); // Preserve the original error code
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
}
// Decrypt the ciphertext in RAM
- DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
+ DecryptDataUnits ((uint8 *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
// Conceal initial portion of the filesystem
if (workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE)
{
// We are decrypting the initial TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE bytes of the filesystem. We will
// conceal this portion to prevent Windows and applications from interfering with the volume.
for (i = 0; i < min (TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET + workChunkSize); i++)
buf[i] ^= TC_NTFS_CONCEAL_CONSTANT;
}
// Write the plaintext
offset.QuadPart = workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET;
if (MoveFilePointer (dev, offset) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (WriteFile (dev, buf, workChunkSize, &n, NULL) == 0)
{
// Write error
nStatus = ERR_OS_ERROR;
goto closing_seq;
@@ -1816,125 +1816,125 @@ closing_seq:
TCfree (tmpSectorBuf);
tmpSectorBuf = NULL;
}
if (skippedBadSectorCount > 0)
{
wchar_t msg[30000] = {0};
wchar_t sizeStr[500] = {0};
GetSizeString (skippedBadSectorCount * sectorSize, sizeStr, sizeof(sizeStr));
StringCbPrintfW (msg, sizeof(msg),
GetString ("SKIPPED_BAD_SECTOR_COUNT"),
skippedBadSectorCount,
sizeStr);
WarningDirect (msg, hwndDlg);
}
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;
+ uint8 *header;
DWORD dwError;
uint32 headerCrc32;
- byte *fieldPos;
+ uint8 *fieldPos;
PCRYPTO_INFO pCryptoInfo = headerCryptoInfo;
#ifdef _WIN64
BOOL bIsRamEncryptionEnabled = IsRamEncryptionEnabled();
#endif
- header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
+ header = (uint8 *) 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;
+ fieldPos = (uint8 *) header + TC_HEADER_OFFSET_ENCRYPTED_AREA_START;
offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE;
if (MoveFilePointer (dev, offset) == 0
|| !ReadEffectiveVolumeHeader (TRUE, dev, header, &n) || n < TC_VOLUME_HEADER_EFFECTIVE_SIZE)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
#ifdef _WIN64
if (bIsRamEncryptionEnabled)
{
pCryptoInfo = crypto_open();
if (!pCryptoInfo)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
memcpy (pCryptoInfo, headerCryptoInfo, sizeof (CRYPTO_INFO));
VcUnprotectKeys (pCryptoInfo, VcGetEncryptionID (headerCryptoInfo));
}
#endif
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, pCryptoInfo);
if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241)
{
nStatus = ERR_PARAMETER_INCORRECT;
goto closing_seq;
}
mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaStart.Value));
mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaLength.Value));
// We need to ensure the TC_HEADER_FLAG_NONSYS_INPLACE_ENC flag bit is set, because if volumes created by TC-format
// were decrypted in place, it would be possible to mount them partially encrypted and it wouldn't be possible
// to resume interrupted decryption after the wizard exits.
masterCryptoInfo->HeaderFlags |= TC_HEADER_FLAG_NONSYS_INPLACE_ENC;
- fieldPos = (byte *) header + TC_HEADER_OFFSET_FLAGS;
+ fieldPos = (uint8 *) header + TC_HEADER_OFFSET_FLAGS;
mputLong (fieldPos, (masterCryptoInfo->HeaderFlags));
headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
- fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC;
+ fieldPos = (uint8 *) header + TC_HEADER_OFFSET_HEADER_CRC;
mputLong (fieldPos, headerCrc32);
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, pCryptoInfo);
if (MoveFilePointer (dev, offset) == 0
|| !WriteEffectiveVolumeHeader (TRUE, dev, header))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
closing_seq:
dwError = GetLastError();
#ifdef _WIN64
if (bIsRamEncryptionEnabled && pCryptoInfo)
{
crypto_close(pCryptoInfo);
}
#endif
burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
TCfree (header);
if (nStatus != ERR_SUCCESS)
SetLastError (dwError);
@@ -2181,94 +2181,97 @@ BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm,
}
else if (!bDecrypt)
{
if (newWipeAlgorithm != TC_WIPE_NONE)
{
StringCbPrintfA (str, sizeof(str), "%d", (int) newWipeAlgorithm);
SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), (DWORD) strlen(str), FALSE, FALSE);
}
else if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)))
{
_wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE));
}
}
StringCbPrintfA (str, sizeof(str), "%d", count);
return SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), (DWORD) strlen(str), FALSE, FALSE);
}
// This function moves the file pointer to the given offset. It first retrieves the current
// file position using SetFilePointerEx() with FILE_CURRENT as the reference point, and then
// calculates the difference between the current position and the desired position. Subsequently,
// it moves the file pointer by the difference calculated using SetFilePointerEx() again.
//
// This approach of moving the file pointer relatively (instead of absolutely) was implemented
// as a workaround to address the performance issues related to in-place encryption. When using
// SetFilePointerEx() with FILE_BEGIN as the reference point, reaching the end of large drives
// during in-place encryption can cause significant slowdowns. By moving the file pointer
// relatively, these performance issues are mitigated.
+//
+// We fall back to absolute positioning if the relative positioning fails.
BOOL MoveFilePointer (HANDLE dev, LARGE_INTEGER offset)
{
LARGE_INTEGER currOffset;
LARGE_INTEGER diffOffset;
currOffset.QuadPart = 0;
- if (SetFilePointerEx (dev, currOffset, &currOffset, FILE_CURRENT) == 0)
- return FALSE;
-
- diffOffset.QuadPart = offset.QuadPart - currOffset.QuadPart;
- if (diffOffset.QuadPart == 0)
- return TRUE;
+ if (SetFilePointerEx (dev, currOffset, &currOffset, FILE_CURRENT))
+ {
+ diffOffset.QuadPart = offset.QuadPart - currOffset.QuadPart;
+ if (diffOffset.QuadPart == 0)
+ return TRUE;
- // Moves the file pointer by the difference between current and desired positions
- if (SetFilePointerEx (dev, diffOffset, NULL, FILE_CURRENT) == 0)
- return FALSE;
+ // Moves the file pointer by the difference between current and desired positions
+ if (SetFilePointerEx (dev, diffOffset, NULL, FILE_CURRENT))
+ return TRUE;
+ }
- return TRUE;
+ // An error occurred, fallback to absolute positioning
+ return SetFilePointerEx (dev, offset, NULL, FILE_BEGIN);
}
// Repairs damaged sectors (i.e. those with read errors) by zeroing them.
// Note that this operating fails if there are any write errors.
int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount)
{
int nStatus;
DWORD n;
int64 sectorCount;
LARGE_INTEGER workOffset;
- byte *sectorBuffer = NULL;
+ uint8 *sectorBuffer = NULL;
DWORD dwError;
workOffset.QuadPart = startOffset.QuadPart;
- sectorBuffer = (byte *) TCalloc (sectorSize);
+ sectorBuffer = (uint8 *) TCalloc (sectorSize);
if (!sectorBuffer)
return ERR_OUTOFMEMORY;
if (!MoveFilePointer(dev, workOffset))
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount)
{
if (ReadFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0)
{
memset (sectorBuffer, 0, sectorSize);
// If ReadFile failed, move back to start of the unreadable sector
if (MoveFilePointer (dev, workOffset) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
if (WriteFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
++(*zeroedSectorCount);
@@ -2285,93 +2288,93 @@ closing_seq:
if (sectorBuffer != NULL)
TCfree (sectorBuffer);
if (nStatus != ERR_SUCCESS)
SetLastError (dwError);
return nStatus;
}
static int OpenBackupHeader (HANDLE dev, const wchar_t *devicePath, Password *password, int pkcs5, int pim, PCRYPTO_INFO *retMasterCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize)
{
LARGE_INTEGER offset;
DWORD n;
int nStatus = ERR_SUCCESS;
char *header;
DWORD dwError;
header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
if (!header)
return ERR_OUTOFMEMORY;
VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE;
if (MoveFilePointer (dev, offset) == 0
- || !ReadEffectiveVolumeHeader (TRUE, dev, (byte *) header, &n) || n < TC_VOLUME_HEADER_EFFECTIVE_SIZE)
+ || !ReadEffectiveVolumeHeader (TRUE, dev, (uint8 *) header, &n) || n < TC_VOLUME_HEADER_EFFECTIVE_SIZE)
{
nStatus = ERR_OS_ERROR;
goto closing_seq;
}
nStatus = ReadVolumeHeader (FALSE, header, password, pkcs5, pim, retMasterCryptoInfo, headerCryptoInfo);
if (nStatus != ERR_SUCCESS)
goto closing_seq;
closing_seq:
dwError = GetLastError();
burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
TCfree (header);
dwError = GetLastError();
if (nStatus != ERR_SUCCESS)
SetLastError (dwError);
return nStatus;
}
static BOOL GetFreeClusterBeforeThreshold (HANDLE volumeHandle, int64 *freeCluster, int64 clusterThreshold)
{
const int bitmapSize = 65536;
- byte bitmapBuffer[bitmapSize + sizeof (VOLUME_BITMAP_BUFFER)];
+ uint8 bitmapBuffer[bitmapSize + sizeof (VOLUME_BITMAP_BUFFER)];
VOLUME_BITMAP_BUFFER *bitmap = (VOLUME_BITMAP_BUFFER *) bitmapBuffer;
STARTING_LCN_INPUT_BUFFER startLcn;
startLcn.StartingLcn.QuadPart = 0;
DWORD bytesReturned;
while (DeviceIoControl (volumeHandle, FSCTL_GET_VOLUME_BITMAP, &startLcn, sizeof (startLcn), &bitmapBuffer, sizeof (bitmapBuffer), &bytesReturned, NULL)
|| GetLastError() == ERROR_MORE_DATA)
{
for (int64 bitmapIndex = 0; bitmapIndex < min (bitmapSize, (bitmap->BitmapSize.QuadPart / 8)); ++bitmapIndex)
{
if (bitmap->StartingLcn.QuadPart + bitmapIndex * 8 >= clusterThreshold)
goto err;
if (bitmap->Buffer[bitmapIndex] != 0xff)
{
for (int bit = 0; bit < 8; ++bit)
{
if ((bitmap->Buffer[bitmapIndex] & (1 << bit)) == 0)
{
*freeCluster = bitmap->StartingLcn.QuadPart + bitmapIndex * 8 + bit;
if (*freeCluster >= clusterThreshold)
goto err;
return TRUE;
}
}
}
}