|
|
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
7: this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
1.1.1.14 root 8: by the TrueCrypt License 2.5 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.10 root 29: #include "../Format/FormatCom.h"
1.1.1.3 root 30:
1.1.1.14 root 31:
32: uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize)
33: {
34: uint64 reservedSize;
35:
36: if (hiddenVolume)
37: {
38: // Reserve free space at the end of the host filesystem
39: if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD)
40: reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE;
41: else
42: 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
43: }
44: else
45: {
46: reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
47: }
48:
49: if (volumeSize < reservedSize)
50: return 0;
51:
52: return volumeSize - reservedSize;
53: }
54:
55:
1.1.1.15! root 56: int FormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
1.1 root 57: {
58: int nStatus;
1.1.1.12 root 59: PCRYPTO_INFO cryptoInfo = NULL;
1.1.1.4 root 60: HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.10 root 61: DWORD dwError;
1.1.1.14 root 62: char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1.1.4 root 63: unsigned __int64 num_sectors, startSector;
1.1.1.3 root 64: fatparams ft;
1.1.1.4 root 65: FILETIME ftCreationTime;
66: FILETIME ftLastWriteTime;
67: FILETIME ftLastAccessTime;
68: BOOL bTimeStampValid = FALSE;
1.1.1.12 root 69: BOOL bInstantRetryOtherFilesys = FALSE;
1.1.1.10 root 70: char dosDev[TC_MAX_PATH] = { 0 };
71: char devName[MAX_PATH] = { 0 };
72: int driveLetter = -1;
73: WCHAR deviceName[MAX_PATH];
1.1.1.14 root 74: uint64 dataOffset;
75: LARGE_INTEGER offset;
1.1.1.10 root 76:
1.1.1.12 root 77: /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
1.1.1.14 root 78: less than TC_MAX_FAT_FS_SIZE, the user is asked within this function whether he wants to instantly
1.1.1.12 root 79: retry FAT format instead (to avoid having to re-create the whole container again). If the user
80: answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed
81: and some destructive operations that were performed during the first attempt must be (and are) skipped.
82: Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
83: determine whether they (or their portions) need to be skipped during such a second attempt; if so,
84: use the 'bInstantRetryOtherFilesys' flag to skip them. */
85:
1.1.1.15! root 86: if (volParams->hiddenVol)
1.1.1.14 root 87: {
1.1.1.15! root 88: dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
1.1.1.14 root 89: }
90: else
91: {
1.1.1.15! root 92: if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE)
1.1.1.14 root 93: return ERR_VOL_SIZE_WRONG;
94:
95: dataOffset = TC_VOLUME_DATA_OFFSET;
96: }
97:
1.1.1.15! root 98: volParams->size = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);
1.1 root 99:
1.1.1.15! root 100: num_sectors = volParams->size / SECTOR_SIZE;
1.1.1.10 root 101:
1.1.1.15! root 102: if (volParams->bDevice)
1.1.1.10 root 103: {
1.1.1.15! root 104: strcpy ((char *)deviceName, volParams->volumePath);
1.1.1.10 root 105: ToUNICODE ((char *)deviceName);
106:
107: driveLetter = GetDiskDeviceDriveLetter (deviceName);
108: }
109:
1.1.1.3 root 110: VirtualLock (header, sizeof (header));
1.1 root 111:
1.1.1.12 root 112: /* Copies any header structures into header, but does not do any disk I/O */
113: nStatus = VolumeWriteHeader (FALSE,
114: header,
1.1.1.15! root 115: volParams->ea,
1.1.1.12 root 116: FIRST_MODE_OF_OPERATION_ID,
1.1.1.15! root 117: volParams->password,
! 118: volParams->pkcs5,
1.1.1.12 root 119: NULL,
1.1.1.4 root 120: &cryptoInfo,
1.1.1.15! root 121: volParams->size,
! 122: volParams->hiddenVol ? volParams->size : 0,
1.1.1.14 root 123: dataOffset,
1.1.1.15! root 124: volParams->size,
1.1.1.14 root 125: 0,
1.1.1.15! root 126: volParams->headerFlags,
1.1.1.6 root 127: FALSE);
1.1 root 128:
129: if (nStatus != 0)
1.1.1.3 root 130: {
131: burn (header, sizeof (header));
132: VirtualUnlock (header, sizeof (header));
1.1 root 133: return nStatus;
1.1.1.3 root 134: }
135:
1.1.1.12 root 136: begin_format:
137:
1.1.1.15! root 138: if (volParams->bDevice)
1.1.1.3 root 139: {
1.1.1.10 root 140: /* Device-hosted volume */
1.1.1.14 root 141:
1.1.1.11 root 142: DWORD dwResult;
1.1.1.10 root 143: int nPass;
144:
1.1.1.15! root 145: if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0)
1.1.1.14 root 146: return ERR_OS_ERROR;
1.1.1.10 root 147:
148: if (IsDeviceMounted (devName))
149: {
150: if ((dev = DismountDrive (devName)) == INVALID_HANDLE_VALUE)
1.1.1.4 root 151: {
1.1.1.11 root 152: Error ("FORMAT_CANT_DISMOUNT_FILESYS");
153: nStatus = ERR_DONT_REPORT;
154: goto error;
1.1.1.10 root 155: }
156: }
157: else if (nCurrentOS == WIN_VISTA_OR_LATER && driveLetter == -1)
158: {
159: // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition
160: // to which no drive letter has been assigned under the system. This problem can be worked
161: // around by assigning a drive letter to the partition temporarily.
162:
163: char szDriveLetter[] = { 'A', ':', 0 };
164: char rootPath[] = { 'A', ':', '\\', 0 };
165: char uniqVolName[MAX_PATH+1] = { 0 };
166: int tmpDriveLetter = -1;
167: BOOL bResult = FALSE;
168:
169: tmpDriveLetter = GetFirstAvailableDrive ();
170:
171: if (tmpDriveLetter != -1)
172: {
173: rootPath[0] += tmpDriveLetter;
174: szDriveLetter[0] += tmpDriveLetter;
175:
1.1.1.15! root 176: if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
1.1.1.10 root 177: {
178: bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
179:
180: DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
181: szDriveLetter,
1.1.1.15! root 182: volParams->volumePath);
1.1.1.10 root 183:
184: if (bResult
185: && SetVolumeMountPoint (rootPath, uniqVolName))
186: {
1.1.1.14 root 187: // The drive letter can be removed now
1.1.1.10 root 188: DeleteVolumeMountPoint (rootPath);
189: }
190: }
191: }
192: }
193:
194: // Perform open - 'quick format' - close - open to prevent Windows from restoring NTFS boot sector backup
195: for (nPass = 0; nPass < 2; nPass++)
196: {
1.1.1.14 root 197: int retryCount;
198:
199: retryCount = 0;
200:
1.1.1.10 root 201: // Try exclusive access mode first
1.1.1.14 root 202: // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
203: while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
204: {
1.1.1.10 root 205: dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
206:
1.1.1.14 root 207: if (retryCount > 1)
208: Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
209: }
210:
1.1.1.10 root 211: if (dev == INVALID_HANDLE_VALUE)
212: {
1.1.1.14 root 213: // Exclusive access denied -- retry in shared mode
1.1.1.10 root 214: dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
215: if (dev != INVALID_HANDLE_VALUE)
216: {
1.1.1.15! root 217: if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
1.1.1.10 root 218: {
219: nStatus = ERR_DONT_REPORT;
220: goto error;
221: }
222: }
223: else
224: {
1.1.1.14 root 225: nStatus = ERR_OS_ERROR;
1.1.1.10 root 226: goto error;
227: }
228: }
229:
1.1.1.15! root 230: if (volParams->hiddenVol || bInstantRetryOtherFilesys)
1.1.1.10 root 231: break; // The following "quick format" operation would damage the outer volume
232:
233: if (nPass == 0)
234: {
235: char buf[65536];
236: DWORD bw;
237:
238: // Pseudo "quick format" to prevent Windows from restoring NTFS boot sector backup
239: memset (buf, 0, sizeof (buf));
240: WriteFile (dev, buf, sizeof (buf), &bw, NULL);
241: FlushFileBuffers (dev);
242: CloseHandle (dev);
243: dev = INVALID_HANDLE_VALUE;
1.1.1.4 root 244: }
245: }
1.1.1.11 root 246:
247: if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
248: {
249: Error ("FORMAT_CANT_DISMOUNT_FILESYS");
250: nStatus = ERR_DONT_REPORT;
251: goto error;
252: }
1.1.1.3 root 253: }
254: else
255: {
1.1.1.10 root 256: /* File-hosted volume */
257:
1.1.1.4 root 258: // We could support FILE_ATTRIBUTE_HIDDEN as an option
259: // (Now if the container has hidden or system file attribute, the OS will not allow
260: // overwritting it; so the user will have to delete it manually).
1.1.1.15! root 261: dev = CreateFile (volParams->volumePath, GENERIC_WRITE,
! 262: (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
! 263: NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6 root 264:
1.1.1.8 root 265: if (dev == INVALID_HANDLE_VALUE)
266: {
1.1.1.14 root 267: nStatus = ERR_OS_ERROR;
1.1.1.8 root 268: goto error;
269: }
270:
1.1.1.15! root 271: if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
1.1.1.6 root 272: {
273: LARGE_INTEGER volumeSize;
1.1.1.15! root 274: volumeSize.QuadPart = volParams->size + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.6 root 275:
1.1.1.15! root 276: if (volParams->sparseFileSwitch && volParams->quickFormat)
1.1.1.8 root 277: {
278: // Create as sparse file container
279: DWORD tmp;
280: if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
281: {
1.1.1.14 root 282: nStatus = ERR_OS_ERROR;
1.1.1.8 root 283: goto error;
284: }
285: }
286:
287: // Preallocate the file
1.1.1.6 root 288: if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
289: || !SetEndOfFile (dev)
290: || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
291: {
1.1.1.14 root 292: nStatus = ERR_OS_ERROR;
1.1.1.7 root 293: goto error;
1.1.1.6 root 294: }
295: }
1.1.1.3 root 296: }
297:
1.1.1.15! root 298: if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
1.1.1.4 root 299: {
300: /* Remember the container timestamp (used to reset file date and time of file-hosted
301: containers to preserve plausible deniability of hidden volume) */
302: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
303: {
304: bTimeStampValid = FALSE;
1.1.1.15! root 305: MessageBoxW (volParams->hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4 root 306: }
307: else
308: bTimeStampValid = TRUE;
1.1.1.3 root 309: }
1.1 root 310:
1.1.1.15! root 311: KillTimer (volParams->hwndDlg, 0xff);
1.1 root 312:
1.1.1.6 root 313: /* Volume header */
1.1.1.4 root 314:
315: // Hidden volume setup
1.1.1.15! root 316: if (volParams->hiddenVol)
1.1.1.4 root 317: {
1.1.1.14 root 318: LARGE_INTEGER headerOffset;
319:
1.1.1.15! root 320: // Check hidden volume volParams->size
! 321: if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
1.1.1.4 root 322: {
1.1.1.7 root 323: nStatus = ERR_VOL_SIZE_WRONG;
324: goto error;
1.1.1.4 root 325: }
326:
327: // Seek to hidden volume header location
1.1.1.14 root 328:
329: headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
330:
331: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.4 root 332: {
1.1.1.14 root 333: nStatus = ERR_OS_ERROR;
1.1.1.7 root 334: goto error;
1.1.1.4 root 335: }
336: }
1.1.1.12 root 337: else if (bInstantRetryOtherFilesys)
338: {
339: // The previous file system format failed and the user wants to try again with a different file system.
340: // The volume header had been written successfully so we need to seek to the byte after the header.
341:
1.1.1.14 root 342: LARGE_INTEGER offset;
343: offset.QuadPart = TC_VOLUME_DATA_OFFSET;
344: if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
1.1.1.12 root 345: {
1.1.1.14 root 346: nStatus = ERR_OS_ERROR;
1.1.1.12 root 347: goto error;
348: }
349: }
1.1.1.4 root 350:
1.1.1.12 root 351: if (!bInstantRetryOtherFilesys)
1.1.1.10 root 352: {
1.1.1.12 root 353: // Write the volume header
1.1.1.14 root 354: if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
1.1.1.12 root 355: {
1.1.1.14 root 356: nStatus = ERR_OS_ERROR;
1.1.1.12 root 357: goto error;
358: }
1.1.1.4 root 359:
1.1.1.14 root 360: // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
1.1.1.15! root 361: if (!volParams->hiddenVol)
1.1.1.14 root 362: {
363: byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
364: ZeroMemory (buf, sizeof (buf));
365: if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR)
366: {
367: nStatus = ERR_OS_ERROR;
368: goto error;
369: }
370: }
371: }
1.1.1.4 root 372:
1.1.1.15! root 373: if (volParams->hiddenVol)
1.1.1.4 root 374: {
375: // Calculate data area position of hidden volume
1.1.1.14 root 376: cryptoInfo->hiddenVolumeOffset = dataOffset;
1.1.1.4 root 377:
378: // Validate the offset
1.1.1.14 root 379: if (dataOffset % SECTOR_SIZE != 0)
1.1.1.4 root 380: {
1.1.1.6 root 381: nStatus = ERR_VOL_SIZE_WRONG;
382: goto error;
1.1.1.4 root 383: }
384:
1.1.1.15! root 385: volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant
1.1.1.4 root 386: }
387:
1.1.1.14 root 388: /* Data area */
389: startSector = dataOffset / SECTOR_SIZE;
390:
1.1.1.4 root 391: // Format filesystem
392:
1.1.1.15! root 393: switch (volParams->fileSystem)
1.1.1.3 root 394: {
395: case FILESYS_NONE:
1.1.1.10 root 396: case FILESYS_NTFS:
1.1.1.15! root 397: nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
1.1.1.3 root 398: break;
1.1.1.10 root 399:
1.1.1.3 root 400: case FILESYS_FAT:
1.1.1.4 root 401: if (num_sectors > 0xFFFFffff)
402: {
1.1.1.6 root 403: nStatus = ERR_VOL_SIZE_WRONG;
404: goto error;
1.1.1.4 root 405: }
406:
407: // Calculate the fats, root dir etc
408: ft.num_sectors = (unsigned int) (num_sectors);
1.1.1.15! root 409: ft.cluster_size = volParams->clusterSize;
1.1.1.6 root 410: memcpy (ft.volume_name, "NO NAME ", 11);
1.1.1.4 root 411: GetFatParams (&ft);
1.1.1.15! root 412: *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE;
1.1.1.4 root 413:
1.1.1.15! root 414: nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
1.1.1.3 root 415: break;
1.1.1.13 root 416:
417: default:
418: nStatus = ERR_PARAMETER_INCORRECT;
419: goto error;
1.1.1.3 root 420: }
1.1 root 421:
1.1.1.15! root 422: if (nStatus != ERR_SUCCESS)
! 423: goto error;
! 424:
1.1.1.14 root 425: // Write header backup
1.1.1.15! root 426: offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : volParams->size + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.14 root 427:
428: if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
429: {
430: nStatus = ERR_OS_ERROR;
431: goto error;
432: }
433:
434: nStatus = VolumeWriteHeader (FALSE,
435: header,
1.1.1.15! root 436: volParams->ea,
1.1.1.14 root 437: FIRST_MODE_OF_OPERATION_ID,
1.1.1.15! root 438: volParams->password,
! 439: volParams->pkcs5,
1.1.1.14 root 440: cryptoInfo->master_keydata,
441: &cryptoInfo,
1.1.1.15! root 442: volParams->size,
! 443: volParams->hiddenVol ? volParams->size : 0,
1.1.1.14 root 444: dataOffset,
1.1.1.15! root 445: volParams->size,
1.1.1.14 root 446: 0,
1.1.1.15! root 447: volParams->headerFlags,
1.1.1.14 root 448: FALSE);
449:
450: if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
451: {
452: nStatus = ERR_OS_ERROR;
453: goto error;
454: }
455:
456: // Fill reserved header sectors with random data
1.1.1.15! root 457: if (!volParams->hiddenVol)
1.1.1.14 root 458: {
459: char temporaryKey[MASTER_KEYDATA_SIZE];
460: char originalK2[MASTER_KEYDATA_SIZE];
461:
462: byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
463: BOOL backupHeaders = FALSE;
464:
465: memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
466:
467: while (TRUE)
468: {
469: // Temporary keys
470: if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), TRUE)
471: || !RandgetBytes (cryptoInfo->k2, sizeof (cryptoInfo->k2), FALSE))
472: {
473: nStatus = ERR_PARAMETER_INCORRECT;
474: goto error;
475: }
476:
477: nStatus = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
478: if (nStatus != ERR_SUCCESS)
479: goto error;
480:
481: if (!EAInitMode (cryptoInfo))
482: {
483: nStatus = ERR_MODE_INIT_FAILED;
484: goto error;
485: }
486:
1.1.1.15! root 487: offset.QuadPart = backupHeaders ? volParams->size + TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET;
1.1.1.14 root 488: offset.QuadPart += TC_VOLUME_HEADER_EFFECTIVE_SIZE;
489:
490: if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
491: {
492: nStatus = ERR_OS_ERROR;
493: goto error;
494: }
495:
496: EncryptBuffer (buf, sizeof (buf), cryptoInfo);
497:
498: if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR)
499: {
500: nStatus = ERR_OS_ERROR;
501: goto error;
502: }
503:
504: if (backupHeaders)
505: break;
506:
507: backupHeaders = TRUE;
508: }
509:
510: memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
511:
512: nStatus = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
513: if (nStatus != ERR_SUCCESS)
514: goto error;
515:
516: if (!EAInitMode (cryptoInfo))
517: {
518: nStatus = ERR_MODE_INIT_FAILED;
519: goto error;
520: }
521:
522: burn (temporaryKey, sizeof (temporaryKey));
523: burn (originalK2, sizeof (originalK2));
524: }
525:
1.1.1.10 root 526: error:
527: dwError = GetLastError();
1.1.1.3 root 528:
529: burn (header, sizeof (header));
530: VirtualUnlock (header, sizeof (header));
1.1 root 531:
1.1.1.11 root 532: if (dev != INVALID_HANDLE_VALUE)
1.1.1.4 root 533: {
1.1.1.15! root 534: if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
1.1.1.11 root 535: {
536: // Remove preallocated part before closing file handle if format failed
537: if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
538: SetEndOfFile (dev);
539: }
1.1.1.6 root 540:
1.1.1.11 root 541: FlushFileBuffers (dev);
1.1.1.4 root 542:
1.1.1.11 root 543: if (bTimeStampValid)
544: {
545: // Restore the container timestamp (to preserve plausible deniability of the hidden volume)
546: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.15! root 547: MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.11 root 548: }
549:
550: CloseHandle (dev);
551: dev = INVALID_HANDLE_VALUE;
552: }
1.1 root 553:
1.1.1.6 root 554: if (nStatus != 0)
1.1.1.3 root 555: {
1.1.1.10 root 556: SetLastError(dwError);
1.1.1.12 root 557: goto fv_end;
1.1.1.10 root 558: }
1.1.1.6 root 559:
1.1.1.15! root 560: if (volParams->fileSystem == FILESYS_NTFS)
1.1.1.10 root 561: {
562: // Quick-format volume as NTFS
563: int driveNo = GetLastAvailableDrive ();
564: MountOptions mountOptions;
565: int retCode;
1.1.1.3 root 566:
1.1.1.10 root 567: ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5 root 568:
1.1.1.10 root 569: if (driveNo == -1)
570: {
1.1.1.15! root 571: MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
! 572: MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3 root 573:
1.1.1.12 root 574: nStatus = ERR_NO_FREE_DRIVES;
575: goto fv_end;
1.1.1.10 root 576: }
1.1.1.4 root 577:
1.1.1.10 root 578: mountOptions.ReadOnly = FALSE;
579: mountOptions.Removable = FALSE;
580: mountOptions.ProtectHiddenVolume = FALSE;
581: mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.13 root 582: mountOptions.PartitionInInactiveSysEncScope = FALSE;
1.1.1.14 root 583: mountOptions.UseBackupHeader = FALSE;
1.1.1.3 root 584:
1.1.1.15! root 585: if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
1.1.1.10 root 586: {
1.1.1.15! root 587: MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
! 588: MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.12 root 589: nStatus = ERR_VOL_MOUNT_FAILED;
590: goto fv_end;
1.1.1.10 root 591: }
1.1.1.3 root 592:
1.1.1.10 root 593: if (!IsAdmin () && IsUacSupported ())
1.1.1.15! root 594: retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
1.1.1.10 root 595: else
1.1.1.15! root 596: retCode = FormatNtfs (driveNo, volParams->clusterSize);
1.1.1.3 root 597:
1.1.1.10 root 598: if (retCode != TRUE)
599: {
1.1.1.15! root 600: if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
! 601: MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3 root 602:
1.1.1.15! root 603: if (volParams->size <= TC_MAX_FAT_FS_SIZE)
1.1.1.12 root 604: {
605: if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
606: {
607: // NTFS format failed and the user wants to try FAT format immediately
1.1.1.15! root 608: volParams->fileSystem = FILESYS_FAT;
1.1.1.12 root 609: bInstantRetryOtherFilesys = TRUE;
1.1.1.15! root 610: volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted
! 611: volParams->clusterSize = 0; // Default cluster size
1.1.1.12 root 612: goto begin_format;
613: }
614: }
615: else
616: Error ("FORMAT_NTFS_FAILED");
617:
618: nStatus = ERR_DONT_REPORT;
619: goto fv_end;
1.1.1.3 root 620: }
1.1.1.10 root 621:
1.1.1.15! root 622: if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
! 623: MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3 root 624: }
625:
1.1.1.12 root 626: fv_end:
627:
628: if (dosDev[0])
1.1.1.15! root 629: RemoveFakeDosName (volParams->volumePath, dosDev);
1.1.1.12 root 630:
631: crypto_close (cryptoInfo);
632:
1.1 root 633: return nStatus;
1.1.1.3 root 634: }
1.1 root 635:
1.1.1.3 root 636:
1.1.1.8 root 637: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3 root 638: {
639: int write_buf_cnt = 0;
1.1.1.14 root 640: char sector[SECTOR_SIZE], write_buf[WRITE_BUF_SIZE];
1.1.1.4 root 641: unsigned __int64 nSecNo = startSector;
1.1.1.12 root 642: int retVal = 0;
643: char temporaryKey[MASTER_KEYDATA_SIZE];
644: char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4 root 645:
1.1.1.8 root 646: LARGE_INTEGER startOffset;
647: LARGE_INTEGER newOffset;
648:
1.1.1.4 root 649: // Seek to start sector
650: startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6 root 651: if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
652: || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4 root 653: {
1.1.1.14 root 654: return ERR_OS_ERROR;
1.1.1.4 root 655: }
1.1.1.12 root 656:
657: VirtualLock (temporaryKey, sizeof (temporaryKey));
658: VirtualLock (originalK2, sizeof (originalK2));
1.1.1.3 root 659:
660: memset (sector, 0, sizeof (sector));
661:
1.1.1.12 root 662: // Remember the original secondary key (XTS mode) before generating a temporary one
663: memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
664:
1.1.1.7 root 665: /* Fill the rest of the data area with random data */
666:
1.1.1.3 root 667: if(!quickFormat)
668: {
1.1.1.7 root 669: /* Generate a random temporary key set to be used for "dummy" encryption that will fill
670: the free disk space (data area) with random data. This is necessary for plausible
1.1.1.12 root 671: deniability of hidden volumes. */
1.1.1.6 root 672:
1.1.1.9 root 673: // Temporary master key
674: if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
675: goto fail;
1.1.1.12 root 676:
677: // Temporary secondary key (XTS mode)
678: if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9 root 679: goto fail;
1.1.1.7 root 680:
681: retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12 root 682: if (retVal != ERR_SUCCESS)
683: goto fail;
684:
1.1.1.7 root 685: if (!EAInitMode (cryptoInfo))
686: {
1.1.1.12 root 687: retVal = ERR_MODE_INIT_FAILED;
688: goto fail;
1.1.1.7 root 689: }
1.1.1.4 root 690:
1.1.1.3 root 691: while (num_sectors--)
692: {
1.1.1.12 root 693: /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
694: since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do
695: occur commonly on media in the "real world", so it might actually be a fatal mistake
696: to try to avoid them completely. */
1.1.1.9 root 697:
1.1.1.12 root 698: #if RNG_POOL_SIZE < SECTOR_SIZE
699: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7 root 700: #endif
701:
1.1.1.12 root 702: if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9 root 703: goto fail;
1.1.1.14 root 704:
1.1.1.7 root 705: // Encrypt the random plaintext and write it to the disk
1.1.1.6 root 706: if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8 root 707: cryptoInfo) == FALSE)
1.1.1.3 root 708: goto fail;
709: }
1.1.1.14 root 710:
711: if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1.1.3 root 712: goto fail;
713: }
714: else
715: nSecNo = num_sectors;
716:
717: UpdateProgressBar (nSecNo);
718:
1.1.1.12 root 719: // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
720: memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
721:
722: // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
723: retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
724: if (retVal != ERR_SUCCESS)
725: goto fail;
726: if (!EAInitMode (cryptoInfo))
727: {
728: retVal = ERR_MODE_INIT_FAILED;
729: goto fail;
730: }
731:
1.1.1.7 root 732: burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12 root 733: burn (originalK2, sizeof(originalK2));
734: VirtualUnlock (temporaryKey, sizeof (temporaryKey));
735: VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.3 root 736: return 0;
737:
738: fail:
739:
1.1.1.7 root 740: burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12 root 741: burn (originalK2, sizeof(originalK2));
742: VirtualUnlock (temporaryKey, sizeof (temporaryKey));
743: VirtualUnlock (originalK2, sizeof (originalK2));
744: return (retVal ? retVal : ERR_OS_ERROR);
1.1 root 745: }
1.1.1.3 root 746:
747:
748: volatile BOOLEAN FormatExResult;
749:
750: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
751: {
752: if (command == FMIFS_DONE)
753: FormatExResult = *(BOOLEAN *) parameter;
754: return TRUE;
755: }
756:
757: BOOL FormatNtfs (int driveNo, int clusterSize)
758: {
759: WCHAR dir[8] = { driveNo + 'A', 0 };
760: PFORMATEX FormatEx;
761: HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10 root 762: int i;
1.1.1.3 root 763:
764: if (hModule == NULL)
765: return FALSE;
766:
767: if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
768: {
769: FreeLibrary (hModule);
770: return FALSE;
771: }
772:
773: wcscat (dir, L":\\");
774:
775: FormatExResult = FALSE;
776:
1.1.1.12 root 777: // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10 root 778: // It often helps to retry several times.
779: for (i = 0; i < 10 && FormatExResult != TRUE; i++)
780: {
1.1.1.11 root 781: FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10 root 782: }
1.1.1.3 root 783:
784: FreeLibrary (hModule);
785: return FormatExResult;
786: }
787:
1.1.1.8 root 788:
1.1.1.12 root 789: BOOL WriteSector (void *dev, char *sector,
1.1.1.3 root 790: char *write_buf, int *write_buf_cnt,
1.1.1.8 root 791: __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3 root 792: {
1.1.1.8 root 793: static __int32 updateTime = 0;
1.1.1.4 root 794:
1.1.1.12 root 795: (*nSecNo)++;
1.1.1.4 root 796:
1.1.1.3 root 797: memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
798: (*write_buf_cnt) += SECTOR_SIZE;
799:
1.1.1.14 root 800: if (*write_buf_cnt == WRITE_BUF_SIZE && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
801: return FALSE;
1.1.1.6 root 802:
803: if (GetTickCount () - updateTime > 25)
1.1.1.3 root 804: {
1.1.1.6 root 805: if (UpdateProgressBar (*nSecNo))
1.1.1.3 root 806: return FALSE;
1.1.1.6 root 807:
808: updateTime = GetTickCount ();
1.1.1.3 root 809: }
810:
811: return TRUE;
812:
813: }
1.1.1.14 root 814:
815:
816: BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
817: {
818: UINT64_STRUCT unitNo;
819: DWORD bytesWritten;
820:
821: if (*write_buf_cnt == 0)
822: return TRUE;
823:
824: unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
825:
826: EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
827:
828: if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
829: return FALSE;
830:
831: *write_buf_cnt = 0;
832: return TRUE;
833: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.