format.c
来自「使用visual studio 2005 开发的开源文件、磁盘加密软件。这是6.」· C语言 代码 · 共 975 行 · 第 1/2 页
C
975 行
// Write header backup
offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
nStatus = CreateVolumeHeaderInMemory (FALSE,
header,
volParams->ea,
FIRST_MODE_OF_OPERATION_ID,
volParams->password,
volParams->pkcs5,
cryptoInfo->master_keydata,
&cryptoInfo,
dataAreaSize,
volParams->hiddenVol ? dataAreaSize : 0,
dataOffset,
dataAreaSize,
0,
volParams->headerFlags,
FALSE);
if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
{
nStatus = ERR_OS_ERROR;
goto error;
}
// Fill reserved header sectors (including the backup header area) with random data
if (!volParams->hiddenVol)
{
nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
if (nStatus != ERR_SUCCESS)
goto error;
}
error:
dwError = GetLastError();
burn (header, sizeof (header));
VirtualUnlock (header, sizeof (header));
if (dev != INVALID_HANDLE_VALUE)
{
if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
{
// Remove preallocated part before closing file handle if format failed
if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
SetEndOfFile (dev);
}
FlushFileBuffers (dev);
if (bTimeStampValid)
{
// Restore the container timestamp (to preserve plausible deniability of the hidden volume)
if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
}
CloseHandle (dev);
dev = INVALID_HANDLE_VALUE;
}
if (nStatus != 0)
{
SetLastError(dwError);
goto fv_end;
}
if (volParams->fileSystem == FILESYS_NTFS)
{
// Quick-format volume as NTFS
int driveNo = GetLastAvailableDrive ();
MountOptions mountOptions;
int retCode;
ZeroMemory (&mountOptions, sizeof (mountOptions));
if (driveNo == -1)
{
MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
nStatus = ERR_NO_FREE_DRIVES;
goto fv_end;
}
mountOptions.ReadOnly = FALSE;
mountOptions.Removable = FALSE;
mountOptions.ProtectHiddenVolume = FALSE;
mountOptions.PreserveTimestamp = bPreserveTimestamp;
mountOptions.PartitionInInactiveSysEncScope = FALSE;
mountOptions.UseBackupHeader = FALSE;
if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
{
MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
nStatus = ERR_VOL_MOUNT_FAILED;
goto fv_end;
}
if (!IsAdmin () && IsUacSupported ())
retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
else
retCode = FormatNtfs (driveNo, volParams->clusterSize);
if (retCode != TRUE)
{
if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
if (dataAreaSize <= TC_MAX_FAT_FS_SIZE)
{
if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
{
// NTFS format failed and the user wants to try FAT format immediately
volParams->fileSystem = FILESYS_FAT;
bInstantRetryOtherFilesys = TRUE;
volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted
volParams->clusterSize = 0; // Default cluster size
goto begin_format;
}
}
else
Error ("FORMAT_NTFS_FAILED");
nStatus = ERR_DONT_REPORT;
goto fv_end;
}
if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
}
fv_end:
if (dosDev[0])
RemoveFakeDosName (volParams->volumePath, dosDev);
crypto_close (cryptoInfo);
return nStatus;
}
int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
{
int write_buf_cnt = 0;
char sector[SECTOR_SIZE], write_buf[WRITE_BUF_SIZE];
unsigned __int64 nSecNo = startSector;
int retVal = 0;
DWORD err;
char temporaryKey[MASTER_KEYDATA_SIZE];
char originalK2[MASTER_KEYDATA_SIZE];
LARGE_INTEGER startOffset;
LARGE_INTEGER newOffset;
// Seek to start sector
startOffset.QuadPart = startSector * SECTOR_SIZE;
if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
|| newOffset.QuadPart != startOffset.QuadPart)
{
return ERR_OS_ERROR;
}
VirtualLock (temporaryKey, sizeof (temporaryKey));
VirtualLock (originalK2, sizeof (originalK2));
memset (sector, 0, sizeof (sector));
// Remember the original secondary key (XTS mode) before generating a temporary one
memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
/* Fill the rest of the data area with random data */
if(!quickFormat)
{
/* Generate a random temporary key set to be used for "dummy" encryption that will fill
the free disk space (data area) with random data. This is necessary for plausible
deniability of hidden volumes. */
// Temporary master key
if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
goto fail;
// Temporary secondary key (XTS mode)
if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
goto fail;
retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
if (retVal != ERR_SUCCESS)
goto fail;
if (!EAInitMode (cryptoInfo))
{
retVal = ERR_MODE_INIT_FAILED;
goto fail;
}
while (num_sectors--)
{
/* Generate random plaintext. Note that reused plaintext blocks are not a concern here
since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do
occur commonly on media in the "real world", so it might actually be a fatal mistake
to try to avoid them completely. */
#if RNG_POOL_SIZE < SECTOR_SIZE
#error RNG_POOL_SIZE < SECTOR_SIZE
#endif
if (!RandpeekBytes (sector, SECTOR_SIZE))
goto fail;
// Encrypt the random plaintext and write it to the disk
if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
cryptoInfo) == FALSE)
goto fail;
}
if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
goto fail;
}
else
nSecNo = num_sectors;
UpdateProgressBar (nSecNo);
// Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
// Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
if (retVal != ERR_SUCCESS)
goto fail;
if (!EAInitMode (cryptoInfo))
{
retVal = ERR_MODE_INIT_FAILED;
goto fail;
}
burn (temporaryKey, sizeof(temporaryKey));
burn (originalK2, sizeof(originalK2));
VirtualUnlock (temporaryKey, sizeof (temporaryKey));
VirtualUnlock (originalK2, sizeof (originalK2));
return 0;
fail:
err = GetLastError();
burn (temporaryKey, sizeof(temporaryKey));
burn (originalK2, sizeof(originalK2));
VirtualUnlock (temporaryKey, sizeof (temporaryKey));
VirtualUnlock (originalK2, sizeof (originalK2));
SetLastError (err);
return (retVal ? retVal : ERR_OS_ERROR);
}
volatile BOOLEAN FormatExResult;
BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
{
if (command == FMIFS_DONE)
FormatExResult = *(BOOLEAN *) parameter;
return TRUE;
}
BOOL FormatNtfs (int driveNo, int clusterSize)
{
WCHAR dir[8] = { driveNo + 'A', 0 };
PFORMATEX FormatEx;
HMODULE hModule = LoadLibrary ("fmifs.dll");
int i;
if (hModule == NULL)
return FALSE;
if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
{
FreeLibrary (hModule);
return FALSE;
}
wcscat (dir, L":\\");
FormatExResult = FALSE;
// Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
// It often helps to retry several times.
for (i = 0; i < 10 && FormatExResult != TRUE; i++)
{
FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
}
FreeLibrary (hModule);
return FormatExResult;
}
BOOL WriteSector (void *dev, char *sector,
char *write_buf, int *write_buf_cnt,
__int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
{
static __int32 updateTime = 0;
(*nSecNo)++;
memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
(*write_buf_cnt) += SECTOR_SIZE;
if (*write_buf_cnt == WRITE_BUF_SIZE && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
return FALSE;
if (GetTickCount () - updateTime > 25)
{
if (UpdateProgressBar (*nSecNo))
return FALSE;
updateTime = GetTickCount ();
}
return TRUE;
}
static volatile BOOL WriteThreadRunning;
static volatile BOOL WriteThreadExitRequested;
static HANDLE WriteThreadHandle;
static byte *WriteThreadBuffer;
static HANDLE WriteBufferEmptyEvent;
static HANDLE WriteBufferFullEvent;
static volatile HANDLE WriteRequestHandle;
static volatile int WriteRequestSize;
static volatile DWORD WriteRequestResult;
static void __cdecl FormatWriteThreadProc (void *arg)
{
DWORD bytesWritten;
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
while (!WriteThreadExitRequested)
{
if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
{
handleWin32Error (NULL);
break;
}
if (WriteThreadExitRequested)
break;
if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
WriteRequestResult = GetLastError();
else
WriteRequestResult = ERROR_SUCCESS;
if (!SetEvent (WriteBufferEmptyEvent))
{
handleWin32Error (NULL);
break;
}
}
WriteThreadRunning = FALSE;
_endthread();
}
static BOOL StartFormatWriteThread ()
{
DWORD sysErr;
WriteBufferEmptyEvent = NULL;
WriteBufferFullEvent = NULL;
WriteThreadBuffer = NULL;
WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
if (!WriteBufferEmptyEvent)
goto err;
WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!WriteBufferFullEvent)
goto err;
WriteThreadBuffer = TCalloc (WRITE_BUF_SIZE);
if (!WriteThreadBuffer)
{
SetLastError (ERROR_OUTOFMEMORY);
goto err;
}
WriteThreadExitRequested = FALSE;
WriteRequestResult = ERROR_SUCCESS;
WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL);
if ((uintptr_t) WriteThreadHandle == -1L)
goto err;
WriteThreadRunning = TRUE;
return TRUE;
err:
sysErr = GetLastError();
if (WriteBufferEmptyEvent)
CloseHandle (WriteBufferEmptyEvent);
if (WriteBufferFullEvent)
CloseHandle (WriteBufferFullEvent);
if (WriteThreadBuffer)
TCfree (WriteThreadBuffer);
SetLastError (sysErr);
return FALSE;
}
static void StopFormatWriteThread ()
{
if (WriteThreadRunning)
{
WaitForSingleObject (WriteBufferEmptyEvent, INFINITE);
WriteThreadExitRequested = TRUE;
SetEvent (WriteBufferFullEvent);
WaitForSingleObject (WriteThreadHandle, INFINITE);
}
CloseHandle (WriteBufferEmptyEvent);
CloseHandle (WriteBufferFullEvent);
TCfree (WriteThreadBuffer);
}
BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
{
UINT64_STRUCT unitNo;
DWORD bytesWritten;
if (*write_buf_cnt == 0)
return TRUE;
unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
if (WriteThreadRunning)
{
if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED)
return FALSE;
if (WriteRequestResult != ERROR_SUCCESS)
{
SetLastError (WriteRequestResult);
return FALSE;
}
memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt);
WriteRequestHandle = dev;
WriteRequestSize = *write_buf_cnt;
if (!SetEvent (WriteBufferFullEvent))
return FALSE;
}
else
{
if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
return FALSE;
}
*write_buf_cnt = 0;
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?