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