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