|
|
1.1.1.10 root 1: /*
1.1.1.12 root 2: Legal Notice: Some portions of the source code contained in this file were
3: derived from the source code of Encryption for the Masses 2.02a, which is
4: Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
5: Agreement for Encryption for the Masses'. Modifications and additions to
6: the original source code (contained in this file) and all other portions of
1.1.1.17 root 7: this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed
1.1.1.19! root 8: by the TrueCrypt License 2.8 the full text of which is contained in the
1.1.1.12 root 9: file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10 root 10: packages. */
11:
12: #include <stdlib.h>
13: #include <string.h>
1.1.1.6 root 14:
15: #include "Tcdefs.h"
16:
1.1.1.9 root 17: #include "Common.h"
1.1.1.6 root 18: #include "Crypto.h"
19: #include "Fat.h"
20: #include "Format.h"
1.1.1.9 root 21: #include "Random.h"
1.1.1.6 root 22: #include "Volumes.h"
1.1.1.8 root 23:
1.1.1.6 root 24: #include "Apidrvr.h"
25: #include "Dlgcode.h"
26: #include "Language.h"
1.1.1.8 root 27: #include "Progress.h"
1.1.1.6 root 28: #include "Resource.h"
1.1.1.16 root 29: #include "Format/FormatCom.h"
30: #include "Format/Tcformat.h"
1.1.1.3 root 31:
1.1.1.19! root 32: int FormatWriteBufferSize = 1024 * 1024;
! 33:
1.1.1.14 root 34:
35: uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize)
36: {
37: uint64 reservedSize;
38:
39: if (hiddenVolume)
40: {
41: // Reserve free space at the end of the host filesystem
42: if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD)
43: reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE;
44: else
45: reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size
46: }
47: else
48: {
49: reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
50: }
51:
52: if (volumeSize < reservedSize)
53: return 0;
54:
55: return volumeSize - reservedSize;
56: }
57:
58:
1.1.1.16 root 59: int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
1.1 root 60: {
61: int nStatus;
1.1.1.12 root 62: PCRYPTO_INFO cryptoInfo = NULL;
1.1.1.4 root 63: HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.10 root 64: DWORD dwError;
1.1.1.14 root 65: char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1.1.4 root 66: unsigned __int64 num_sectors, startSector;
1.1.1.3 root 67: fatparams ft;
1.1.1.4 root 68: FILETIME ftCreationTime;
69: FILETIME ftLastWriteTime;
70: FILETIME ftLastAccessTime;
71: BOOL bTimeStampValid = FALSE;
1.1.1.12 root 72: BOOL bInstantRetryOtherFilesys = FALSE;
1.1.1.10 root 73: char dosDev[TC_MAX_PATH] = { 0 };
74: char devName[MAX_PATH] = { 0 };
75: int driveLetter = -1;
76: WCHAR deviceName[MAX_PATH];
1.1.1.16 root 77: uint64 dataOffset, dataAreaSize;
1.1.1.14 root 78: LARGE_INTEGER offset;
1.1.1.16 root 79: BOOL bFailedRequiredDASD = FALSE;
80:
1.1.1.10 root 81:
1.1.1.12 root 82: /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
1.1.1.14 root 83: less than TC_MAX_FAT_FS_SIZE, the user is asked within this function whether he wants to instantly
1.1.1.12 root 84: retry FAT format instead (to avoid having to re-create the whole container again). If the user
85: answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed
86: and some destructive operations that were performed during the first attempt must be (and are) skipped.
87: Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
88: determine whether they (or their portions) need to be skipped during such a second attempt; if so,
89: use the 'bInstantRetryOtherFilesys' flag to skip them. */
90:
1.1.1.15 root 91: if (volParams->hiddenVol)
1.1.1.14 root 92: {
1.1.1.15 root 93: dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
1.1.1.14 root 94: }
95: else
96: {
1.1.1.15 root 97: if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE)
1.1.1.14 root 98: return ERR_VOL_SIZE_WRONG;
99:
100: dataOffset = TC_VOLUME_DATA_OFFSET;
101: }
102:
1.1.1.16 root 103: dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);
1.1 root 104:
1.1.1.16 root 105: num_sectors = dataAreaSize / SECTOR_SIZE;
1.1.1.10 root 106:
1.1.1.15 root 107: if (volParams->bDevice)
1.1.1.10 root 108: {
1.1.1.15 root 109: strcpy ((char *)deviceName, volParams->volumePath);
1.1.1.10 root 110: ToUNICODE ((char *)deviceName);
111:
112: driveLetter = GetDiskDeviceDriveLetter (deviceName);
113: }
114:
1.1.1.3 root 115: VirtualLock (header, sizeof (header));
1.1 root 116:
1.1.1.16 root 117: nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.12 root 118: header,
1.1.1.15 root 119: volParams->ea,
1.1.1.12 root 120: FIRST_MODE_OF_OPERATION_ID,
1.1.1.15 root 121: volParams->password,
122: volParams->pkcs5,
1.1.1.12 root 123: NULL,
1.1.1.4 root 124: &cryptoInfo,
1.1.1.16 root 125: dataAreaSize,
126: volParams->hiddenVol ? dataAreaSize : 0,
1.1.1.14 root 127: dataOffset,
1.1.1.16 root 128: dataAreaSize,
1.1.1.14 root 129: 0,
1.1.1.15 root 130: volParams->headerFlags,
1.1.1.6 root 131: FALSE);
1.1 root 132:
133: if (nStatus != 0)
1.1.1.3 root 134: {
135: burn (header, sizeof (header));
136: VirtualUnlock (header, sizeof (header));
1.1 root 137: return nStatus;
1.1.1.3 root 138: }
139:
1.1.1.12 root 140: begin_format:
141:
1.1.1.15 root 142: if (volParams->bDevice)
1.1.1.3 root 143: {
1.1.1.10 root 144: /* Device-hosted volume */
1.1.1.14 root 145:
1.1.1.11 root 146: DWORD dwResult;
1.1.1.10 root 147: int nPass;
148:
1.1.1.15 root 149: if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0)
1.1.1.14 root 150: return ERR_OS_ERROR;
1.1.1.10 root 151:
152: if (IsDeviceMounted (devName))
153: {
1.1.1.16 root 154: if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
1.1.1.4 root 155: {
1.1.1.11 root 156: Error ("FORMAT_CANT_DISMOUNT_FILESYS");
157: nStatus = ERR_DONT_REPORT;
158: goto error;
1.1.1.10 root 159: }
1.1.1.16 root 160:
161: /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver
162: would otherwise prevent us from writing to hidden sectors). */
163:
164: if (!DeviceIoControl (dev,
165: FSCTL_ALLOW_EXTENDED_DASD_IO,
166: NULL,
167: 0,
168: NULL,
169: 0,
170: &dwResult,
171: NULL))
172: {
173: bFailedRequiredDASD = TRUE;
174: }
1.1.1.10 root 175: }
1.1.1.17 root 176: else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
1.1.1.10 root 177: {
178: // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition
179: // to which no drive letter has been assigned under the system. This problem can be worked
180: // around by assigning a drive letter to the partition temporarily.
181:
182: char szDriveLetter[] = { 'A', ':', 0 };
183: char rootPath[] = { 'A', ':', '\\', 0 };
184: char uniqVolName[MAX_PATH+1] = { 0 };
185: int tmpDriveLetter = -1;
186: BOOL bResult = FALSE;
187:
188: tmpDriveLetter = GetFirstAvailableDrive ();
189:
190: if (tmpDriveLetter != -1)
191: {
1.1.1.19! root 192: rootPath[0] += (char) tmpDriveLetter;
! 193: szDriveLetter[0] += (char) tmpDriveLetter;
1.1.1.10 root 194:
1.1.1.15 root 195: if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
1.1.1.10 root 196: {
197: bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
198:
199: DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
200: szDriveLetter,
1.1.1.15 root 201: volParams->volumePath);
1.1.1.10 root 202:
203: if (bResult
204: && SetVolumeMountPoint (rootPath, uniqVolName))
205: {
1.1.1.14 root 206: // The drive letter can be removed now
1.1.1.10 root 207: DeleteVolumeMountPoint (rootPath);
208: }
209: }
210: }
211: }
212:
1.1.1.16 root 213: // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be
214: // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed,
215: // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However,
216: // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly
217: // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result.
218:
219: DeviceIoControl (dev,
220: FSCTL_ALLOW_EXTENDED_DASD_IO,
221: NULL,
222: 0,
223: NULL,
224: 0,
225: &dwResult,
226: NULL);
227:
228:
229: // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open
230: // so that the filesystem driver does not prevent us from formatting hidden sectors.
231: for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++)
1.1.1.10 root 232: {
1.1.1.14 root 233: int retryCount;
234:
235: retryCount = 0;
236:
1.1.1.10 root 237: // Try exclusive access mode first
1.1.1.14 root 238: // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
239: while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
240: {
1.1.1.10 root 241: dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
242:
1.1.1.14 root 243: if (retryCount > 1)
244: Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
245: }
246:
1.1.1.10 root 247: if (dev == INVALID_HANDLE_VALUE)
248: {
1.1.1.14 root 249: // Exclusive access denied -- retry in shared mode
1.1.1.10 root 250: dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
251: if (dev != INVALID_HANDLE_VALUE)
252: {
1.1.1.15 root 253: if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
1.1.1.10 root 254: {
255: nStatus = ERR_DONT_REPORT;
256: goto error;
257: }
258: }
259: else
260: {
1.1.1.16 root 261: handleWin32Error (volParams->hwndDlg);
262: Error ("CANT_ACCESS_VOL");
263: nStatus = ERR_DONT_REPORT;
1.1.1.10 root 264: goto error;
265: }
266: }
267:
1.1.1.15 root 268: if (volParams->hiddenVol || bInstantRetryOtherFilesys)
1.1.1.10 root 269: break; // The following "quick format" operation would damage the outer volume
270:
271: if (nPass == 0)
272: {
1.1.1.16 root 273: char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
1.1.1.10 root 274: DWORD bw;
275:
1.1.1.16 root 276: // Perform pseudo "quick format" so that the filesystem driver does not prevent us from
277: // formatting hidden sectors
1.1.1.10 root 278: memset (buf, 0, sizeof (buf));
1.1.1.16 root 279:
280: if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
281: {
282: nStatus = ERR_OS_ERROR;
283: goto error;
284: }
285:
1.1.1.10 root 286: FlushFileBuffers (dev);
287: CloseHandle (dev);
288: dev = INVALID_HANDLE_VALUE;
1.1.1.4 root 289: }
290: }
1.1.1.11 root 291:
292: if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
293: {
294: Error ("FORMAT_CANT_DISMOUNT_FILESYS");
295: nStatus = ERR_DONT_REPORT;
296: goto error;
297: }
1.1.1.3 root 298: }
299: else
300: {
1.1.1.10 root 301: /* File-hosted volume */
302:
1.1.1.19! root 303: dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
1.1.1.15 root 304: (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
305: NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6 root 306:
1.1.1.8 root 307: if (dev == INVALID_HANDLE_VALUE)
308: {
1.1.1.14 root 309: nStatus = ERR_OS_ERROR;
1.1.1.8 root 310: goto error;
311: }
312:
1.1.1.19! root 313: DisableFileCompression (dev);
! 314:
1.1.1.15 root 315: if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
1.1.1.6 root 316: {
317: LARGE_INTEGER volumeSize;
1.1.1.16 root 318: volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.6 root 319:
1.1.1.15 root 320: if (volParams->sparseFileSwitch && volParams->quickFormat)
1.1.1.8 root 321: {
322: // Create as sparse file container
323: DWORD tmp;
324: if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
325: {
1.1.1.14 root 326: nStatus = ERR_OS_ERROR;
1.1.1.8 root 327: goto error;
328: }
329: }
330:
331: // Preallocate the file
1.1.1.6 root 332: if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
333: || !SetEndOfFile (dev)
334: || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
335: {
1.1.1.14 root 336: nStatus = ERR_OS_ERROR;
1.1.1.7 root 337: goto error;
1.1.1.6 root 338: }
339: }
1.1.1.3 root 340: }
341:
1.1.1.15 root 342: if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
1.1.1.4 root 343: {
344: /* Remember the container timestamp (used to reset file date and time of file-hosted
345: containers to preserve plausible deniability of hidden volume) */
346: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
347: {
348: bTimeStampValid = FALSE;
1.1.1.15 root 349: MessageBoxW (volParams->hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4 root 350: }
351: else
352: bTimeStampValid = TRUE;
1.1.1.3 root 353: }
1.1 root 354:
1.1.1.16 root 355: KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
1.1 root 356:
1.1.1.6 root 357: /* Volume header */
1.1.1.4 root 358:
359: // Hidden volume setup
1.1.1.15 root 360: if (volParams->hiddenVol)
1.1.1.4 root 361: {
1.1.1.14 root 362: LARGE_INTEGER headerOffset;
363:
1.1.1.16 root 364: // Check hidden volume size
1.1.1.15 root 365: if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
1.1.1.4 root 366: {
1.1.1.7 root 367: nStatus = ERR_VOL_SIZE_WRONG;
368: goto error;
1.1.1.4 root 369: }
370:
371: // Seek to hidden volume header location
1.1.1.14 root 372:
373: headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
374:
375: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.4 root 376: {
1.1.1.14 root 377: nStatus = ERR_OS_ERROR;
1.1.1.7 root 378: goto error;
1.1.1.4 root 379: }
380: }
1.1.1.12 root 381: else if (bInstantRetryOtherFilesys)
382: {
383: // The previous file system format failed and the user wants to try again with a different file system.
384: // The volume header had been written successfully so we need to seek to the byte after the header.
385:
1.1.1.14 root 386: LARGE_INTEGER offset;
387: offset.QuadPart = TC_VOLUME_DATA_OFFSET;
388: if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
1.1.1.12 root 389: {
1.1.1.14 root 390: nStatus = ERR_OS_ERROR;
1.1.1.12 root 391: goto error;
392: }
393: }
1.1.1.4 root 394:
1.1.1.12 root 395: if (!bInstantRetryOtherFilesys)
1.1.1.10 root 396: {
1.1.1.12 root 397: // Write the volume header
1.1.1.14 root 398: if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
1.1.1.12 root 399: {
1.1.1.14 root 400: nStatus = ERR_OS_ERROR;
1.1.1.12 root 401: goto error;
402: }
1.1.1.4 root 403:
1.1.1.14 root 404: // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
1.1.1.15 root 405: if (!volParams->hiddenVol)
1.1.1.14 root 406: {
407: byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
408: ZeroMemory (buf, sizeof (buf));
409: if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR)
410: {
411: nStatus = ERR_OS_ERROR;
412: goto error;
413: }
414: }
415: }
1.1.1.4 root 416:
1.1.1.15 root 417: if (volParams->hiddenVol)
1.1.1.4 root 418: {
419: // Calculate data area position of hidden volume
1.1.1.14 root 420: cryptoInfo->hiddenVolumeOffset = dataOffset;
1.1.1.4 root 421:
422: // Validate the offset
1.1.1.14 root 423: if (dataOffset % SECTOR_SIZE != 0)
1.1.1.4 root 424: {
1.1.1.6 root 425: nStatus = ERR_VOL_SIZE_WRONG;
426: goto error;
1.1.1.4 root 427: }
428:
1.1.1.15 root 429: volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant
1.1.1.4 root 430: }
431:
1.1.1.14 root 432: /* Data area */
433: startSector = dataOffset / SECTOR_SIZE;
434:
1.1.1.4 root 435: // Format filesystem
436:
1.1.1.15 root 437: switch (volParams->fileSystem)
1.1.1.3 root 438: {
439: case FILESYS_NONE:
1.1.1.10 root 440: case FILESYS_NTFS:
1.1.1.16 root 441:
442: if (volParams->bDevice && !StartFormatWriteThread())
443: {
444: nStatus = ERR_OS_ERROR;
445: goto error;
446: }
447:
1.1.1.15 root 448: nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
1.1.1.16 root 449:
450: if (volParams->bDevice)
451: StopFormatWriteThread();
452:
1.1.1.3 root 453: break;
1.1.1.10 root 454:
1.1.1.3 root 455: case FILESYS_FAT:
1.1.1.4 root 456: if (num_sectors > 0xFFFFffff)
457: {
1.1.1.6 root 458: nStatus = ERR_VOL_SIZE_WRONG;
459: goto error;
1.1.1.4 root 460: }
461:
462: // Calculate the fats, root dir etc
463: ft.num_sectors = (unsigned int) (num_sectors);
1.1.1.15 root 464: ft.cluster_size = volParams->clusterSize;
1.1.1.6 root 465: memcpy (ft.volume_name, "NO NAME ", 11);
1.1.1.4 root 466: GetFatParams (&ft);
1.1.1.15 root 467: *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE;
1.1.1.4 root 468:
1.1.1.16 root 469: if (volParams->bDevice && !StartFormatWriteThread())
470: {
471: nStatus = ERR_OS_ERROR;
472: goto error;
473: }
474:
1.1.1.15 root 475: nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
1.1.1.16 root 476:
477: if (volParams->bDevice)
478: StopFormatWriteThread();
479:
1.1.1.3 root 480: break;
1.1.1.13 root 481:
482: default:
483: nStatus = ERR_PARAMETER_INCORRECT;
484: goto error;
1.1.1.3 root 485: }
1.1 root 486:
1.1.1.15 root 487: if (nStatus != ERR_SUCCESS)
488: goto error;
489:
1.1.1.14 root 490: // Write header backup
1.1.1.16 root 491: offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.14 root 492:
493: if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
494: {
495: nStatus = ERR_OS_ERROR;
496: goto error;
497: }
498:
1.1.1.16 root 499: nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.14 root 500: header,
1.1.1.15 root 501: volParams->ea,
1.1.1.14 root 502: FIRST_MODE_OF_OPERATION_ID,
1.1.1.15 root 503: volParams->password,
504: volParams->pkcs5,
1.1.1.14 root 505: cryptoInfo->master_keydata,
506: &cryptoInfo,
1.1.1.16 root 507: dataAreaSize,
508: volParams->hiddenVol ? dataAreaSize : 0,
1.1.1.14 root 509: dataOffset,
1.1.1.16 root 510: dataAreaSize,
1.1.1.14 root 511: 0,
1.1.1.15 root 512: volParams->headerFlags,
1.1.1.14 root 513: FALSE);
514:
515: if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
516: {
517: nStatus = ERR_OS_ERROR;
518: goto error;
519: }
520:
1.1.1.16 root 521: // Fill reserved header sectors (including the backup header area) with random data
1.1.1.15 root 522: if (!volParams->hiddenVol)
1.1.1.14 root 523: {
1.1.1.16 root 524: nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
1.1.1.14 root 525:
526: if (nStatus != ERR_SUCCESS)
527: goto error;
528: }
529:
1.1.1.19! root 530: #ifndef DEBUG
! 531: if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS)
! 532: Sleep (500); // User-friendly GUI
! 533: #endif
! 534:
1.1.1.10 root 535: error:
536: dwError = GetLastError();
1.1.1.3 root 537:
538: burn (header, sizeof (header));
539: VirtualUnlock (header, sizeof (header));
1.1 root 540:
1.1.1.11 root 541: if (dev != INVALID_HANDLE_VALUE)
1.1.1.4 root 542: {
1.1.1.15 root 543: if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
1.1.1.11 root 544: {
545: // Remove preallocated part before closing file handle if format failed
546: if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
547: SetEndOfFile (dev);
548: }
1.1.1.6 root 549:
1.1.1.11 root 550: FlushFileBuffers (dev);
1.1.1.4 root 551:
1.1.1.11 root 552: if (bTimeStampValid)
553: {
554: // Restore the container timestamp (to preserve plausible deniability of the hidden volume)
555: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.15 root 556: MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.11 root 557: }
558:
559: CloseHandle (dev);
560: dev = INVALID_HANDLE_VALUE;
561: }
1.1 root 562:
1.1.1.6 root 563: if (nStatus != 0)
1.1.1.3 root 564: {
1.1.1.10 root 565: SetLastError(dwError);
1.1.1.12 root 566: goto fv_end;
1.1.1.10 root 567: }
1.1.1.6 root 568:
1.1.1.15 root 569: if (volParams->fileSystem == FILESYS_NTFS)
1.1.1.10 root 570: {
571: // Quick-format volume as NTFS
572: int driveNo = GetLastAvailableDrive ();
573: MountOptions mountOptions;
574: int retCode;
1.1.1.3 root 575:
1.1.1.10 root 576: ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5 root 577:
1.1.1.10 root 578: if (driveNo == -1)
579: {
1.1.1.15 root 580: MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
581: MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3 root 582:
1.1.1.12 root 583: nStatus = ERR_NO_FREE_DRIVES;
584: goto fv_end;
1.1.1.10 root 585: }
1.1.1.4 root 586:
1.1.1.10 root 587: mountOptions.ReadOnly = FALSE;
588: mountOptions.Removable = FALSE;
589: mountOptions.ProtectHiddenVolume = FALSE;
590: mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.13 root 591: mountOptions.PartitionInInactiveSysEncScope = FALSE;
1.1.1.14 root 592: mountOptions.UseBackupHeader = FALSE;
1.1.1.3 root 593:
1.1.1.15 root 594: if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
1.1.1.10 root 595: {
1.1.1.15 root 596: MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
597: MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.12 root 598: nStatus = ERR_VOL_MOUNT_FAILED;
599: goto fv_end;
1.1.1.10 root 600: }
1.1.1.3 root 601:
1.1.1.10 root 602: if (!IsAdmin () && IsUacSupported ())
1.1.1.15 root 603: retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
1.1.1.10 root 604: else
1.1.1.15 root 605: retCode = FormatNtfs (driveNo, volParams->clusterSize);
1.1.1.3 root 606:
1.1.1.10 root 607: if (retCode != TRUE)
608: {
1.1.1.15 root 609: if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
610: MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3 root 611:
1.1.1.16 root 612: if (dataAreaSize <= TC_MAX_FAT_FS_SIZE)
1.1.1.12 root 613: {
614: if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
615: {
616: // NTFS format failed and the user wants to try FAT format immediately
1.1.1.15 root 617: volParams->fileSystem = FILESYS_FAT;
1.1.1.12 root 618: bInstantRetryOtherFilesys = TRUE;
1.1.1.15 root 619: volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted
620: volParams->clusterSize = 0; // Default cluster size
1.1.1.12 root 621: goto begin_format;
622: }
623: }
624: else
625: Error ("FORMAT_NTFS_FAILED");
626:
627: nStatus = ERR_DONT_REPORT;
628: goto fv_end;
1.1.1.3 root 629: }
1.1.1.10 root 630:
1.1.1.15 root 631: if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
632: MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3 root 633: }
634:
1.1.1.12 root 635: fv_end:
1.1.1.17 root 636: dwError = GetLastError();
1.1.1.12 root 637:
638: if (dosDev[0])
1.1.1.15 root 639: RemoveFakeDosName (volParams->volumePath, dosDev);
1.1.1.12 root 640:
641: crypto_close (cryptoInfo);
642:
1.1.1.17 root 643: SetLastError (dwError);
1.1 root 644: return nStatus;
1.1.1.3 root 645: }
1.1 root 646:
1.1.1.3 root 647:
1.1.1.8 root 648: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3 root 649: {
650: int write_buf_cnt = 0;
1.1.1.17 root 651: char sector[SECTOR_SIZE], *write_buf;
1.1.1.4 root 652: unsigned __int64 nSecNo = startSector;
1.1.1.12 root 653: int retVal = 0;
1.1.1.16 root 654: DWORD err;
1.1.1.12 root 655: char temporaryKey[MASTER_KEYDATA_SIZE];
656: char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4 root 657:
1.1.1.8 root 658: LARGE_INTEGER startOffset;
659: LARGE_INTEGER newOffset;
660:
1.1.1.4 root 661: // Seek to start sector
662: startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6 root 663: if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
664: || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4 root 665: {
1.1.1.14 root 666: return ERR_OS_ERROR;
1.1.1.4 root 667: }
1.1.1.12 root 668:
1.1.1.19! root 669: write_buf = (char *)TCalloc (FormatWriteBufferSize);
1.1.1.17 root 670: if (!write_buf)
671: return ERR_OUTOFMEMORY;
672:
1.1.1.12 root 673: VirtualLock (temporaryKey, sizeof (temporaryKey));
674: VirtualLock (originalK2, sizeof (originalK2));
1.1.1.3 root 675:
676: memset (sector, 0, sizeof (sector));
677:
1.1.1.12 root 678: // Remember the original secondary key (XTS mode) before generating a temporary one
679: memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
680:
1.1.1.7 root 681: /* Fill the rest of the data area with random data */
682:
1.1.1.3 root 683: if(!quickFormat)
684: {
1.1.1.7 root 685: /* Generate a random temporary key set to be used for "dummy" encryption that will fill
686: the free disk space (data area) with random data. This is necessary for plausible
1.1.1.12 root 687: deniability of hidden volumes. */
1.1.1.6 root 688:
1.1.1.9 root 689: // Temporary master key
690: if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
691: goto fail;
1.1.1.12 root 692:
693: // Temporary secondary key (XTS mode)
694: if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9 root 695: goto fail;
1.1.1.7 root 696:
697: retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12 root 698: if (retVal != ERR_SUCCESS)
699: goto fail;
700:
1.1.1.7 root 701: if (!EAInitMode (cryptoInfo))
702: {
1.1.1.12 root 703: retVal = ERR_MODE_INIT_FAILED;
704: goto fail;
1.1.1.7 root 705: }
1.1.1.4 root 706:
1.1.1.3 root 707: while (num_sectors--)
708: {
1.1.1.12 root 709: /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
710: since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do
711: occur commonly on media in the "real world", so it might actually be a fatal mistake
712: to try to avoid them completely. */
1.1.1.9 root 713:
1.1.1.12 root 714: #if RNG_POOL_SIZE < SECTOR_SIZE
715: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7 root 716: #endif
717:
1.1.1.12 root 718: if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9 root 719: goto fail;
1.1.1.14 root 720:
1.1.1.7 root 721: // Encrypt the random plaintext and write it to the disk
1.1.1.6 root 722: if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8 root 723: cryptoInfo) == FALSE)
1.1.1.3 root 724: goto fail;
725: }
1.1.1.14 root 726:
727: if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1.1.3 root 728: goto fail;
729: }
730: else
731: nSecNo = num_sectors;
732:
733: UpdateProgressBar (nSecNo);
734:
1.1.1.12 root 735: // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
736: memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
737:
738: // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
739: retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
740: if (retVal != ERR_SUCCESS)
741: goto fail;
742: if (!EAInitMode (cryptoInfo))
743: {
744: retVal = ERR_MODE_INIT_FAILED;
745: goto fail;
746: }
747:
1.1.1.7 root 748: burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12 root 749: burn (originalK2, sizeof(originalK2));
750: VirtualUnlock (temporaryKey, sizeof (temporaryKey));
751: VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17 root 752: TCfree (write_buf);
753:
1.1.1.3 root 754: return 0;
755:
756: fail:
1.1.1.16 root 757: err = GetLastError();
1.1.1.3 root 758:
1.1.1.7 root 759: burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12 root 760: burn (originalK2, sizeof(originalK2));
761: VirtualUnlock (temporaryKey, sizeof (temporaryKey));
762: VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17 root 763: TCfree (write_buf);
1.1.1.16 root 764:
765: SetLastError (err);
1.1.1.12 root 766: return (retVal ? retVal : ERR_OS_ERROR);
1.1 root 767: }
1.1.1.3 root 768:
769:
770: volatile BOOLEAN FormatExResult;
771:
772: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
773: {
774: if (command == FMIFS_DONE)
775: FormatExResult = *(BOOLEAN *) parameter;
776: return TRUE;
777: }
778:
779: BOOL FormatNtfs (int driveNo, int clusterSize)
780: {
1.1.1.19! root 781: WCHAR dir[8] = { (WCHAR) driveNo + 'A', 0 };
1.1.1.3 root 782: PFORMATEX FormatEx;
783: HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10 root 784: int i;
1.1.1.3 root 785:
786: if (hModule == NULL)
787: return FALSE;
788:
1.1.1.19! root 789: if (!(FormatEx = (PFORMATEX) GetProcAddress (GetModuleHandle ("fmifs.dll"), "FormatEx")))
1.1.1.3 root 790: {
791: FreeLibrary (hModule);
792: return FALSE;
793: }
794:
795: wcscat (dir, L":\\");
796:
797: FormatExResult = FALSE;
798:
1.1.1.12 root 799: // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10 root 800: // It often helps to retry several times.
1.1.1.19! root 801: for (i = 0; i < 50 && FormatExResult != TRUE; i++)
1.1.1.10 root 802: {
1.1.1.11 root 803: FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10 root 804: }
1.1.1.3 root 805:
1.1.1.19! root 806: // The device may be referenced for some time after FormatEx() returns
! 807: Sleep (2000);
! 808:
1.1.1.3 root 809: FreeLibrary (hModule);
810: return FormatExResult;
811: }
812:
1.1.1.8 root 813:
1.1.1.12 root 814: BOOL WriteSector (void *dev, char *sector,
1.1.1.3 root 815: char *write_buf, int *write_buf_cnt,
1.1.1.8 root 816: __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3 root 817: {
1.1.1.8 root 818: static __int32 updateTime = 0;
1.1.1.4 root 819:
1.1.1.12 root 820: (*nSecNo)++;
1.1.1.4 root 821:
1.1.1.3 root 822: memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
823: (*write_buf_cnt) += SECTOR_SIZE;
824:
1.1.1.19! root 825: if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
1.1.1.14 root 826: return FALSE;
1.1.1.6 root 827:
828: if (GetTickCount () - updateTime > 25)
1.1.1.3 root 829: {
1.1.1.6 root 830: if (UpdateProgressBar (*nSecNo))
1.1.1.3 root 831: return FALSE;
1.1.1.6 root 832:
833: updateTime = GetTickCount ();
1.1.1.3 root 834: }
835:
836: return TRUE;
837:
838: }
1.1.1.14 root 839:
840:
1.1.1.16 root 841: static volatile BOOL WriteThreadRunning;
842: static volatile BOOL WriteThreadExitRequested;
843: static HANDLE WriteThreadHandle;
844:
845: static byte *WriteThreadBuffer;
846: static HANDLE WriteBufferEmptyEvent;
847: static HANDLE WriteBufferFullEvent;
848:
849: static volatile HANDLE WriteRequestHandle;
850: static volatile int WriteRequestSize;
851: static volatile DWORD WriteRequestResult;
852:
853:
854: static void __cdecl FormatWriteThreadProc (void *arg)
855: {
856: DWORD bytesWritten;
857:
858: SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
859:
860: while (!WriteThreadExitRequested)
861: {
862: if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
863: {
864: handleWin32Error (NULL);
865: break;
866: }
867:
868: if (WriteThreadExitRequested)
869: break;
870:
871: if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
872: WriteRequestResult = GetLastError();
873: else
874: WriteRequestResult = ERROR_SUCCESS;
875:
876: if (!SetEvent (WriteBufferEmptyEvent))
877: {
878: handleWin32Error (NULL);
879: break;
880: }
881: }
882:
883: WriteThreadRunning = FALSE;
884: _endthread();
885: }
886:
887:
888: static BOOL StartFormatWriteThread ()
889: {
890: DWORD sysErr;
891:
892: WriteBufferEmptyEvent = NULL;
893: WriteBufferFullEvent = NULL;
894: WriteThreadBuffer = NULL;
895:
896: WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
897: if (!WriteBufferEmptyEvent)
898: goto err;
899:
900: WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
901: if (!WriteBufferFullEvent)
902: goto err;
903:
1.1.1.19! root 904: WriteThreadBuffer = TCalloc (FormatWriteBufferSize);
1.1.1.16 root 905: if (!WriteThreadBuffer)
906: {
907: SetLastError (ERROR_OUTOFMEMORY);
908: goto err;
909: }
910:
911: WriteThreadExitRequested = FALSE;
912: WriteRequestResult = ERROR_SUCCESS;
913:
914: WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL);
915: if ((uintptr_t) WriteThreadHandle == -1L)
916: goto err;
917:
918: WriteThreadRunning = TRUE;
919: return TRUE;
920:
921: err:
922: sysErr = GetLastError();
923:
924: if (WriteBufferEmptyEvent)
925: CloseHandle (WriteBufferEmptyEvent);
926: if (WriteBufferFullEvent)
927: CloseHandle (WriteBufferFullEvent);
928: if (WriteThreadBuffer)
929: TCfree (WriteThreadBuffer);
930:
931: SetLastError (sysErr);
932: return FALSE;
933: }
934:
935:
936: static void StopFormatWriteThread ()
937: {
938: if (WriteThreadRunning)
939: {
940: WaitForSingleObject (WriteBufferEmptyEvent, INFINITE);
941:
942: WriteThreadExitRequested = TRUE;
943: SetEvent (WriteBufferFullEvent);
944:
945: WaitForSingleObject (WriteThreadHandle, INFINITE);
946: }
947:
948: CloseHandle (WriteBufferEmptyEvent);
949: CloseHandle (WriteBufferFullEvent);
950: TCfree (WriteThreadBuffer);
951: }
952:
953:
1.1.1.14 root 954: BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
955: {
956: UINT64_STRUCT unitNo;
957: DWORD bytesWritten;
958:
959: if (*write_buf_cnt == 0)
960: return TRUE;
961:
962: unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
963:
964: EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
965:
1.1.1.16 root 966: if (WriteThreadRunning)
967: {
968: if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED)
969: return FALSE;
970:
971: if (WriteRequestResult != ERROR_SUCCESS)
972: {
1.1.1.17 root 973: SetEvent (WriteBufferEmptyEvent);
1.1.1.16 root 974: SetLastError (WriteRequestResult);
975: return FALSE;
976: }
977:
978: memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt);
979: WriteRequestHandle = dev;
980: WriteRequestSize = *write_buf_cnt;
981:
982: if (!SetEvent (WriteBufferFullEvent))
983: return FALSE;
984: }
985: else
986: {
987: if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
988: return FALSE;
989: }
1.1.1.14 root 990:
991: *write_buf_cnt = 0;
992: return TRUE;
993: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.