diff options
Diffstat (limited to 'src/ExpandVolume/InitDataArea.c')
-rw-r--r-- | src/ExpandVolume/InitDataArea.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/ExpandVolume/InitDataArea.c b/src/ExpandVolume/InitDataArea.c new file mode 100644 index 00000000..a3793e86 --- /dev/null +++ b/src/ExpandVolume/InitDataArea.c @@ -0,0 +1,358 @@ +/* + +Most of the source code contained in this file is taken from the source code of +TrueCrypt 7.0a, which is governed by the TrueCrypt License 3.0 that can be found +in the file 'License.txt' in the folder 'TrueCrypt-License'. + +Modifications and additions to the original source code (contained in this file) +and all other portions of this file are Copyright (c) 2009-2010 by Kih-Oskh or +Copyright (c) 2012-2013 Josef Schneider <josef@netpage.dk> + + +Source code here is copied from 'Common/Format.c' with the following changes: + + - functions removed: + GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize) + TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams) + FormatNtfs (int driveNo, int clusterSize) + FormatExCallback (int command, DWORD subCommand, PVOID parameter) + + - variables removed: + volatile BOOLEAN FormatExResult; + + - removed static linkage class from StartFormatWriteThread() and + StopFormatWriteThread() + + - new functions: + SetFormatSectorSize(uint32 sector_size) + + +------------------------------------------------------------------------------- + +Original legal notice of the TrueCrypt source: + + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions + of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association + and are governed by the TrueCrypt License 3.0 the full text of which is + contained in the file License.txt included in TrueCrypt binary and source + code distribution packages. */ + +#include <stdlib.h> +#include <string.h> + +#include "Tcdefs.h" + +#include "Common.h" +#include "Crypto.h" +#include "Random.h" +#include "Volumes.h" + +#include "Apidrvr.h" +#include "Dlgcode.h" +#include "Language.h" +#include "Progress.h" +#include "Resource.h" + +#include "InitDataArea.h" + +int FormatWriteBufferSize = 1024 * 1024; +static uint32 FormatSectorSize = 0; + +void SetFormatSectorSize(uint32 sector_size) +{ + FormatSectorSize = sector_size; +} + +int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) +{ + int write_buf_cnt = 0; + char sector[TC_MAX_VOLUME_SECTOR_SIZE], *write_buf; + 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 * FormatSectorSize; + if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) + || newOffset.QuadPart != startOffset.QuadPart) + { + return ERR_OS_ERROR; + } + + write_buf = (char *)TCalloc (FormatWriteBufferSize); + if (!write_buf) + return ERR_OUTOFMEMORY; + + 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 (hwndDlg, temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) + goto fail; + + // Temporary secondary key (XTS mode) + if (!RandgetBytes (hwndDlg, 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--) + { + 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 * FormatSectorSize); + + // 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)); + TCfree (write_buf); + + return 0; + +fail: + err = GetLastError(); + + burn (temporaryKey, sizeof(temporaryKey)); + burn (originalK2, sizeof(originalK2)); + VirtualUnlock (temporaryKey, sizeof (temporaryKey)); + VirtualUnlock (originalK2, sizeof (originalK2)); + TCfree (write_buf); + + SetLastError (err); + return (retVal ? retVal : ERR_OS_ERROR); +} + + +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, FormatSectorSize); + (*write_buf_cnt) += FormatSectorSize; + + if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo)) + return FALSE; + + if (GetTickCount () - updateTime > 25) + { + if (UpdateProgressBar (*nSecNo * FormatSectorSize)) + 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(); +} + + +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 (FormatWriteBufferSize); + 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; +} + + +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 * FormatSectorSize - *write_buf_cnt) / 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) + { + SetEvent (WriteBufferEmptyEvent); + 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; +} |