|
|
1.1.1.3 root 1: /* The source code contained in this file has been derived from the source code
2: of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
1.1.1.5 ! root 3: additions to that source code contained in this file are Copyright (c) 2004-2005
1.1.1.4 root 4: TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
1.1.1.3 root 5: parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
6: release. Please see the file license.txt for full license details. */
1.1 root 7:
8: #include "TCdefs.h"
9:
10: #include "crypto.h"
11: #include "fat.h"
12: #include "format.h"
13: #include "volumes.h"
14: #include "progress.h"
15: #include "apidrvr.h"
16: #include "dlgcode.h"
1.1.1.4 root 17: #include "resource.h"
1.1.1.5 ! root 18: #include "common.h"
1.1.1.3 root 19:
1.1 root 20: int
21: FormatVolume (char *lpszFilename,
22: BOOL bDevice,
1.1.1.3 root 23: char *volumePath,
1.1 root 24: unsigned __int64 size,
1.1.1.4 root 25: unsigned __int64 hiddenVolHostSize,
1.1 root 26: char *lpszPassword,
27: int cipher,
28: int pkcs5,
29: BOOL quickFormat,
1.1.1.3 root 30: int fileSystem,
31: int clusterSize,
32: char * summaryMsg,
1.1.1.4 root 33: HWND hwndDlg,
34: BOOL hiddenVol,
35: int *realClusterSize)
1.1 root 36: {
37: int nStatus;
38: PCRYPTO_INFO cryptoInfo;
1.1.1.4 root 39: HANDLE dev = INVALID_HANDLE_VALUE;
1.1 root 40: OPEN_TEST_STRUCT driver;
1.1.1.3 root 41: DWORD dwError, dwThen, dwNow;
1.1 root 42: diskio_f write;
1.1.1.3 root 43: char header[SECTOR_SIZE];
1.1.1.4 root 44: unsigned __int64 num_sectors, startSector;
1.1.1.3 root 45: fatparams ft;
1.1.1.4 root 46: FILETIME ftCreationTime;
47: FILETIME ftLastWriteTime;
48: FILETIME ftLastAccessTime;
49: BOOL bTimeStampValid = FALSE;
1.1.1.3 root 50:
1.1.1.4 root 51: if (!hiddenVol)
52: size -= HEADER_SIZE;
1.1 root 53:
1.1.1.4 root 54: num_sectors = size / SECTOR_SIZE;
1.1.1.3 root 55: VirtualLock (header, sizeof (header));
1.1 root 56:
1.1.1.3 root 57: /* Copies any header structures into header, but does not do any
1.1 root 58: disk io */
1.1.1.3 root 59: nStatus = VolumeWriteHeader (header,
1.1 root 60: cipher,
61: lpszPassword,
62: pkcs5,
63: 0,
64: 0,
1.1.1.4 root 65: &cryptoInfo,
66: hiddenVol ? size : 0);
1.1 root 67:
68: if (nStatus != 0)
1.1.1.3 root 69: {
70: burn (header, sizeof (header));
71: VirtualUnlock (header, sizeof (header));
1.1 root 72: return nStatus;
1.1.1.3 root 73: }
74:
75: write = (diskio_f) _lwrite;
76:
77: if (bDevice == TRUE)
78: {
79: dev = CreateFile (lpszFilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1.1.1.4 root 80: if (dev == INVALID_HANDLE_VALUE)
81: {
82: // Try opening device in shared mode
83: dev = CreateFile (lpszFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
84: if (dev != INVALID_HANDLE_VALUE)
85: {
86: if (IDNO == MessageBox (hwndDlg, getstr (IDS_DEVICE_IN_USE_FORMAT), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
87: {
88: CloseHandle (dev);
89: dev = INVALID_HANDLE_VALUE;
90: }
91: }
92: }
1.1.1.3 root 93: }
94: else
95: {
1.1.1.4 root 96: // We could support FILE_ATTRIBUTE_HIDDEN as an option
97: // (Now if the container has hidden or system file attribute, the OS will not allow
98: // overwritting it; so the user will have to delete it manually).
99: dev = CreateFile (lpszFilename, GENERIC_WRITE,
100: hiddenVol ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
101: NULL, hiddenVol ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.3 root 102: }
103:
104: if (dev == INVALID_HANDLE_VALUE)
105: {
1.1.1.4 root 106: nStatus = ERR_OS_ERROR; goto error;
107: }
108:
109: if (hiddenVol && !bDevice)
110: {
111: /* Remember the container timestamp (used to reset file date and time of file-hosted
112: containers to preserve plausible deniability of hidden volume) */
113: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
114: {
115: bTimeStampValid = FALSE;
116: MessageBox (hwndDlg, getstr (IDS_GETFILETIME_FAILED_IMPLANT), "TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
117: }
118: else
119: bTimeStampValid = TRUE;
1.1.1.3 root 120: }
1.1 root 121:
122: KillTimer (hwndDlg, 0xff);
123:
1.1.1.3 root 124: InitProgressBar (num_sectors);
125: dwThen = GetTickCount ();
1.1.1.2 root 126:
1.1.1.4 root 127:
128: //// Volume header
129:
130: // Hidden volume setup
131: if (hiddenVol)
132: {
133: // Check hidden volume size
134: if (hiddenVolHostSize < MIN_HIDDEN_VOLUME_HOST_SIZE || hiddenVolHostSize > MAX_HIDDEN_VOLUME_HOST_SIZE)
135: {
136: nStatus = ERR_VOL_SIZE_WRONG; goto error;
137: }
138:
139: // Seek to hidden volume header location
140: if (!SeekHiddenVolHeader ((HFILE) dev, hiddenVolHostSize, bDevice))
141: {
142: nStatus = ERR_VOL_SEEKING; goto error;
143: }
144:
145: }
146:
147: // Write the volume header
148: if ((*write) ((HFILE) dev, header, HEADER_SIZE) == HFILE_ERROR)
149: return ERR_OS_ERROR;
150:
151:
152: //// Data area
153:
154: startSector = 1; // Data area of normal volume starts right after volume header
155:
156: if (hiddenVol)
157: {
158: // Calculate data area position of hidden volume
159: unsigned __int64 startOffset = hiddenVolHostSize - size - HIDDEN_VOL_HEADER_OFFSET;
160:
161: // Validate the offset
162: if (startOffset % SECTOR_SIZE != 0)
163: {
164: nStatus = ERR_VOL_SIZE_WRONG; goto error;
165: }
166:
167: startSector = startOffset / SECTOR_SIZE;
168: quickFormat = TRUE; // To entirely format a hidden volume would be redundant
169: }
170:
171: // Format filesystem
172:
1.1.1.3 root 173: switch (fileSystem)
174: {
175: case FILESYS_NONE:
1.1.1.4 root 176: case FILESYS_NTFS: // NTFS volume is just prepared for quick format performed by system
177: nStatus = FormatNoFs (startSector, num_sectors, (HFILE) dev, cryptoInfo, 1000, write, quickFormat);
1.1.1.3 root 178: break;
179:
180: case FILESYS_FAT:
1.1.1.4 root 181: if (num_sectors > 0xFFFFffff)
182: {
183: nStatus = ERR_VOL_SIZE_WRONG; goto error;
184: }
185:
186: // Calculate the fats, root dir etc
187: ft.num_sectors = (unsigned int) (num_sectors);
188: ft.cluster_size = clusterSize;
189: memcpy (ft.volume_name, " ", 11);
190: GetFatParams (&ft);
191: *realClusterSize = ft.cluster_size * SECTOR_SIZE;
192:
193: nStatus = FormatFat (startSector, &ft, (HFILE) dev, cryptoInfo, 1000, write, quickFormat);
1.1.1.3 root 194: break;
195: }
1.1 root 196:
1.1.1.4 root 197: error:
198:
1.1.1.3 root 199: dwNow = GetTickCount ();
200:
201: burn (header, sizeof (header));
202: VirtualUnlock (header, sizeof (header));
1.1 root 203:
204: crypto_close (cryptoInfo);
1.1.1.4 root 205:
206: if (bTimeStampValid)
207: {
208: // Restore the container timestamp (to preserve plausible deniability of the hidden volume)
209: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
210: MessageBox (hwndDlg, getstr (IDS_SETFILETIME_FAILED_IMPLANT), "TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
211: }
212:
1.1.1.3 root 213: CloseHandle (dev);
1.1 root 214:
1.1.1.3 root 215: dwError = GetLastError();
1.1 root 216:
217: if (nStatus!=0)
218: SetLastError(dwError);
1.1.1.3 root 219: else
220: {
221: switch (fileSystem)
222: {
223: case FILESYS_NONE:
224: sprintf (summaryMsg, "Volume size:\t\t%I64d sectors (%I64d MB)\nFile system:\t\tNone"
225: "\n\nFormatting took %lu seconds."
226: , num_sectors, num_sectors*512/1024/1024
227: , (dwNow - dwThen)/1000);
228: break;
229:
230: case FILESYS_FAT:
231: sprintf (summaryMsg,
232: "Volume size:\t\t%d sectors (%I64d MB)\nFile system:\t\tFAT%d\n"
233: "FAT size:\t\t%d bytes\nCluster size:\t\t%d bytes\nClusters available:\t%d"
234: "\n\nFormatting took %lu seconds."
235: , ft.num_sectors, ((__int64) ft.num_sectors*512)/1024/1024, ft.size_fat
236: , (int) (512*ft.fats*ft.fat_length),
237: (int) (512*ft.cluster_size), ft.cluster_count,
238: (dwNow - dwThen)/1000);
239: break;
240:
241: case FILESYS_NTFS:
242: {
1.1.1.4 root 243: // NTFS format is performed by system so we first need to mount the volume
244: int driveNo = GetLastAvailableDrive ();
1.1.1.3 root 245: DWORD os_error;
246: int err;
1.1.1.5 ! root 247: MountOptions mountOptions;
! 248:
1.1.1.3 root 249: if (driveNo == -1)
250: {
1.1.1.4 root 251: MessageBox (hwndDlg, "No free drive letter available. NTFS formatting cannot continue.", lpszTitle, ICON_HAND);
1.1.1.3 root 252: return ERR_NO_FREE_DRIVES;
253: }
254:
1.1.1.5 ! root 255: mountOptions.ReadOnly = FALSE;
! 256: mountOptions.Removable = FALSE;
! 257:
! 258: if (MountVolume (hwndDlg, driveNo, volumePath, lpszPassword, FALSE, TRUE, &mountOptions, FALSE) < 1)
1.1.1.3 root 259: {
260: MessageBox (hwndDlg, "Cannot mount volume. NTFS formatting cannot continue.", lpszTitle, ICON_HAND);
261: return ERR_VOL_MOUNT_FAILED;
262: }
263:
1.1.1.4 root 264: // Quickformat volume as NTFS
1.1.1.3 root 265: if (!FormatNtfs (driveNo, clusterSize))
266: {
1.1.1.4 root 267: MessageBox (hwndDlg, "NTFS formatting failed.\nTry using FAT file system instead.", lpszTitle, MB_ICONERROR);
268:
269: if (!UnmountVolume (hwndDlg, driveNo, FALSE))
270: MessageBox (hwndDlg, "Volume dismount failed.", lpszTitle, MB_ICONERROR);
271:
1.1.1.3 root 272: return ERR_VOL_FORMAT_BAD;
273: }
274:
1.1.1.4 root 275: if (!UnmountVolume (hwndDlg, driveNo, FALSE))
276: MessageBox (hwndDlg, "Formatting succeeded but volume cannot be dismounted.", lpszTitle, MB_ICONEXCLAMATION);
1.1.1.3 root 277:
278: dwNow = GetTickCount ();
279:
280: sprintf (summaryMsg, "Volume size:\t\t%I64d sectors (%I64d MB)\nFile system:\t\tNTFS"
281: "\n\nFormatting took %lu seconds."
282: , num_sectors, num_sectors*512/1024/1024
283: , (dwNow - dwThen)/1000);
284:
285: break;
286: }
287: }
288: }
289:
1.1 root 290: return nStatus;
1.1.1.3 root 291: }
1.1 root 292:
1.1.1.3 root 293:
1.1.1.4 root 294: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, HFILE dev, PCRYPTO_INFO cryptoInfo, int nFrequency, diskio_f write, BOOL quickFormat)
1.1.1.3 root 295: {
296: int write_buf_cnt = 0;
297: char sector[SECTOR_SIZE], *write_buf;
298: int progress = 0;
1.1.1.4 root 299: unsigned __int64 nSecNo = startSector;
300: LARGE_INTEGER startOffset;
301: LARGE_INTEGER newOffset;
302:
303: // Seek to start sector
304: startOffset.QuadPart = startSector * SECTOR_SIZE;
305: if (SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) == 0
306: || newOffset.QuadPart != newOffset.QuadPart)
307: {
308: return ERR_VOL_SEEKING;
309: }
1.1.1.3 root 310:
311: write_buf = TCalloc (WRITE_BUF_SIZE);
312: memset (sector, 0, sizeof (sector));
313:
1.1.1.4 root 314: // Write sectors
1.1.1.3 root 315: if(!quickFormat)
316: {
1.1.1.4 root 317: /* Generate a random key and IV to be used for "dummy" encryption that will fill the
318: free disk space (data area) with random data. That will reduce the amount of
319: predictable plaintext within the volume and also increase the level of plausible
320: deniability of hidden volumes. */
321: char key[DISKKEY_SIZE];
322: RandgetBytes (key, DISKKEY_SIZE, FALSE);
323: RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv, FALSE);
324: EAInit (cryptoInfo->ea, key, cryptoInfo->ks);
325: RandgetBytes (sector, 256, FALSE);
326: RandgetBytes (sector + 256, 256, FALSE);
327:
1.1.1.3 root 328: while (num_sectors--)
329: {
330: if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress,
331: cryptoInfo, nFrequency, write) == FALSE)
332: goto fail;
333: }
334: if (write_buf_cnt != 0 && (*write) (dev, write_buf, write_buf_cnt) == HFILE_ERROR)
335: goto fail;
336: }
337: else
338: nSecNo = num_sectors;
339:
340: UpdateProgressBar (nSecNo);
341:
342: TCfree (write_buf);
343: return 0;
344:
345: fail:
346:
347: TCfree (write_buf);
348: return ERR_OS_ERROR;
1.1 root 349: }
1.1.1.3 root 350:
351:
352: volatile BOOLEAN FormatExResult;
353:
354: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
355: {
356: if (command == FMIFS_DONE)
357: FormatExResult = *(BOOLEAN *) parameter;
358: return TRUE;
359: }
360:
361: BOOL FormatNtfs (int driveNo, int clusterSize)
362: {
363: WCHAR dir[8] = { driveNo + 'A', 0 };
364: PFORMATEX FormatEx;
365: HMODULE hModule = LoadLibrary ("fmifs.dll");
366:
367: if (hModule == NULL)
368: return FALSE;
369:
370: if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
371: {
372: FreeLibrary (hModule);
373: return FALSE;
374: }
375:
376: wcscat (dir, L":\\");
377:
378: FormatExResult = FALSE;
379:
380: if (*(char *)dir > 'C' && *(char *)dir <= 'Z')
381: FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * 512, FormatExCallback);
382:
383: FreeLibrary (hModule);
384: return FormatExResult;
385: }
386:
387: BOOL
388: WriteSector (HFILE dev, char *sector,
389: char *write_buf, int *write_buf_cnt,
390: __int64 *nSecNo, int *progress, PCRYPTO_INFO cryptoInfo,
391: int nFrequency, diskio_f write)
392: {
1.1.1.4 root 393:
394: EncryptSectors ((unsigned long *) sector,
395: (*nSecNo)++, 1, cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->ea);
396:
1.1.1.3 root 397: memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
398: (*write_buf_cnt) += SECTOR_SIZE;
399:
400:
401: if (*write_buf_cnt == WRITE_BUF_SIZE)
402: {
403: if ((*write) (dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR)
404: return FALSE;
405: else
406: *write_buf_cnt = 0;
407: }
408:
409: if (++(*progress) == nFrequency)
410: {
411: if (UpdateProgressBar (*nSecNo) == TRUE)
412: return FALSE;
413: *progress = 0;
414: }
415:
416: return TRUE;
417:
418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.