VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/ExpandVolume/InitDataArea.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ExpandVolume/InitDataArea.c')
-rw-r--r--src/ExpandVolume/InitDataArea.c358
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;
+}