|
|
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; 379: } 1.1 root 380: 1.1.1.10 root 381: error: 382: dwError = GetLastError(); 1.1.1.3 root 383: 384: burn (header, sizeof (header)); 385: VirtualUnlock (header, sizeof (header)); 1.1 root 386: 1.1.1.11 root 387: if (dev != INVALID_HANDLE_VALUE) 1.1.1.4 root 388: { 1.1.1.11 root 389: if (!bDevice && !hiddenVol && nStatus != 0) 390: { 391: // Remove preallocated part before closing file handle if format failed 392: if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0) 393: SetEndOfFile (dev); 394: } 1.1.1.6 root 395: 1.1.1.11 root 396: FlushFileBuffers (dev); 1.1.1.4 root 397: 1.1.1.11 root 398: if (bTimeStampValid) 399: { 400: // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 401: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) 402: MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); 403: } 404: 405: CloseHandle (dev); 406: dev = INVALID_HANDLE_VALUE; 407: } 1.1 root 408: 1.1.1.6 root 409: if (nStatus != 0) 1.1.1.3 root 410: { 1.1.1.10 root 411: SetLastError(dwError); 1.1.1.12! root 412: goto fv_end; 1.1.1.10 root 413: } 1.1.1.6 root 414: 1.1.1.10 root 415: if (fileSystem == FILESYS_NTFS) 416: { 417: // Quick-format volume as NTFS 418: int driveNo = GetLastAvailableDrive (); 419: MountOptions mountOptions; 420: int retCode; 1.1.1.3 root 421: 1.1.1.10 root 422: ZeroMemory (&mountOptions, sizeof (mountOptions)); 1.1.1.5 root 423: 1.1.1.10 root 424: if (driveNo == -1) 425: { 426: MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); 427: MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); 1.1.1.3 root 428: 1.1.1.12! root 429: nStatus = ERR_NO_FREE_DRIVES; ! 430: goto fv_end; 1.1.1.10 root 431: } 1.1.1.4 root 432: 1.1.1.10 root 433: mountOptions.ReadOnly = FALSE; 434: mountOptions.Removable = FALSE; 435: mountOptions.ProtectHiddenVolume = FALSE; 436: mountOptions.PreserveTimestamp = bPreserveTimestamp; 1.1.1.3 root 437: 1.1.1.10 root 438: if (MountVolume (hwndDlg, driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) 439: { 440: MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND); 441: MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); 1.1.1.12! root 442: nStatus = ERR_VOL_MOUNT_FAILED; ! 443: goto fv_end; 1.1.1.10 root 444: } 1.1.1.3 root 445: 1.1.1.10 root 446: if (!IsAdmin () && IsUacSupported ()) 447: retCode = UacFormatNtfs (hwndDlg, driveNo, clusterSize); 448: else 449: retCode = FormatNtfs (driveNo, clusterSize); 1.1.1.3 root 450: 1.1.1.10 root 451: if (retCode != TRUE) 452: { 453: if (!UnmountVolume (hwndDlg, driveNo, FALSE)) 454: MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); 1.1.1.3 root 455: 1.1.1.12! root 456: if (size <= MAX_FAT_VOLUME_SIZE) ! 457: { ! 458: if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES) ! 459: { ! 460: // NTFS format failed and the user wants to try FAT format immediately ! 461: fileSystem = FILESYS_FAT; ! 462: bInstantRetryOtherFilesys = TRUE; ! 463: quickFormat = TRUE; // Volume has already been successfully TC-formatted ! 464: clusterSize = 0; // Default cluster size ! 465: goto begin_format; ! 466: } ! 467: } ! 468: else ! 469: Error ("FORMAT_NTFS_FAILED"); ! 470: ! 471: nStatus = ERR_DONT_REPORT; ! 472: goto fv_end; 1.1.1.3 root 473: } 1.1.1.10 root 474: 475: if (!UnmountVolume (hwndDlg, driveNo, FALSE)) 476: MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); 1.1.1.3 root 477: } 478: 1.1.1.12! root 479: fv_end: ! 480: ! 481: if (dosDev[0]) ! 482: RemoveFakeDosName (volumePath, dosDev); ! 483: ! 484: crypto_close (cryptoInfo); ! 485: 1.1 root 486: return nStatus; 1.1.1.3 root 487: } 1.1 root 488: 1.1.1.12! root 489: #endif // _WIN32 1.1.1.3 root 490: 1.1.1.8 root 491: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) 1.1.1.3 root 492: { 493: int write_buf_cnt = 0; 494: char sector[SECTOR_SIZE], *write_buf; 1.1.1.4 root 495: unsigned __int64 nSecNo = startSector; 1.1.1.12! root 496: int retVal = 0; ! 497: char temporaryKey[MASTER_KEYDATA_SIZE]; ! 498: char originalK2[MASTER_KEYDATA_SIZE]; 1.1.1.4 root 499: 1.1.1.8 root 500: #ifdef _WIN32 501: LARGE_INTEGER startOffset; 502: LARGE_INTEGER newOffset; 503: 1.1.1.4 root 504: // Seek to start sector 505: startOffset.QuadPart = startSector * SECTOR_SIZE; 1.1.1.6 root 506: if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) 507: || newOffset.QuadPart != startOffset.QuadPart) 1.1.1.4 root 508: { 509: return ERR_VOL_SEEKING; 510: } 1.1.1.12! root 511: ! 512: VirtualLock (temporaryKey, sizeof (temporaryKey)); ! 513: VirtualLock (originalK2, sizeof (originalK2)); 1.1.1.8 root 514: #endif 1.1.1.3 root 515: 1.1.1.8 root 516: write_buf = (char *) TCalloc (WRITE_BUF_SIZE); 1.1.1.3 root 517: memset (sector, 0, sizeof (sector)); 518: 1.1.1.12! root 519: // Remember the original secondary key (XTS mode) before generating a temporary one ! 520: memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2)); ! 521: 1.1.1.7 root 522: /* Fill the rest of the data area with random data */ 523: 1.1.1.3 root 524: if(!quickFormat) 525: { 1.1.1.7 root 526: /* Generate a random temporary key set to be used for "dummy" encryption that will fill 527: the free disk space (data area) with random data. This is necessary for plausible 1.1.1.12! root 528: deniability of hidden volumes. */ 1.1.1.6 root 529: 1.1.1.9 root 530: // Temporary master key 531: if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) 532: goto fail; 1.1.1.12! root 533: ! 534: // Temporary secondary key (XTS mode) ! 535: if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE)) 1.1.1.9 root 536: goto fail; 1.1.1.7 root 537: 538: retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); 1.1.1.12! root 539: if (retVal != ERR_SUCCESS) ! 540: goto fail; ! 541: 1.1.1.7 root 542: if (!EAInitMode (cryptoInfo)) 543: { 1.1.1.12! root 544: retVal = ERR_MODE_INIT_FAILED; ! 545: goto fail; 1.1.1.7 root 546: } 1.1.1.4 root 547: 1.1.1.3 root 548: while (num_sectors--) 549: { 1.1.1.12! root 550: /* Generate random plaintext. Note that reused plaintext blocks are not a concern here ! 551: since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do ! 552: occur commonly on media in the "real world", so it might actually be a fatal mistake ! 553: to try to avoid them completely. */ 1.1.1.9 root 554: 1.1.1.12! root 555: #if RNG_POOL_SIZE < SECTOR_SIZE ! 556: #error RNG_POOL_SIZE < SECTOR_SIZE 1.1.1.7 root 557: #endif 558: 1.1.1.9 root 559: #ifdef _WIN32 1.1.1.12! root 560: if (!RandpeekBytes (sector, SECTOR_SIZE)) 1.1.1.9 root 561: goto fail; 562: #else 563: if ((nSecNo & 0x3fff) == 0) 564: { 1.1.1.12! root 565: if (!RandgetBytes (sector, SECTOR_SIZE, FALSE)) 1.1.1.9 root 566: goto fail; 567: } 568: #endif 1.1.1.7 root 569: // Encrypt the random plaintext and write it to the disk 1.1.1.6 root 570: if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, 1.1.1.8 root 571: cryptoInfo) == FALSE) 1.1.1.3 root 572: goto fail; 573: } 1.1.1.8 root 574: if (write_buf_cnt != 0 && 575: #ifdef _WIN32 576: _lwrite ((HFILE)dev, write_buf, write_buf_cnt) == HFILE_ERROR) 577: #else 578: fwrite (write_buf, 1, write_buf_cnt, (FILE *)dev) != (size_t)write_buf_cnt) 579: #endif 1.1.1.3 root 580: goto fail; 581: } 582: else 583: nSecNo = num_sectors; 584: 585: UpdateProgressBar (nSecNo); 586: 1.1.1.12! root 587: // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately ! 588: memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2)); ! 589: ! 590: // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately ! 591: retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks); ! 592: if (retVal != ERR_SUCCESS) ! 593: goto fail; ! 594: if (!EAInitMode (cryptoInfo)) ! 595: { ! 596: retVal = ERR_MODE_INIT_FAILED; ! 597: goto fail; ! 598: } ! 599: ! 600: if (write_buf != NULL) ! 601: TCfree (write_buf); ! 602: 1.1.1.7 root 603: burn (temporaryKey, sizeof(temporaryKey)); 1.1.1.12! root 604: burn (originalK2, sizeof(originalK2)); ! 605: #ifdef _WIN32 ! 606: VirtualUnlock (temporaryKey, sizeof (temporaryKey)); ! 607: VirtualUnlock (originalK2, sizeof (originalK2)); ! 608: #endif 1.1.1.3 root 609: return 0; 610: 611: fail: 612: 1.1.1.12! root 613: if (write_buf != NULL) ! 614: TCfree (write_buf); ! 615: 1.1.1.7 root 616: burn (temporaryKey, sizeof(temporaryKey)); 1.1.1.12! root 617: burn (originalK2, sizeof(originalK2)); ! 618: #ifdef _WIN32 ! 619: VirtualUnlock (temporaryKey, sizeof (temporaryKey)); ! 620: VirtualUnlock (originalK2, sizeof (originalK2)); ! 621: #endif ! 622: return (retVal ? retVal : ERR_OS_ERROR); 1.1 root 623: } 1.1.1.3 root 624: 1.1.1.8 root 625: #ifdef _WIN32 1.1.1.3 root 626: 627: volatile BOOLEAN FormatExResult; 628: 629: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter) 630: { 631: if (command == FMIFS_DONE) 632: FormatExResult = *(BOOLEAN *) parameter; 633: return TRUE; 634: } 635: 636: BOOL FormatNtfs (int driveNo, int clusterSize) 637: { 638: WCHAR dir[8] = { driveNo + 'A', 0 }; 639: PFORMATEX FormatEx; 640: HMODULE hModule = LoadLibrary ("fmifs.dll"); 1.1.1.10 root 641: int i; 1.1.1.3 root 642: 643: if (hModule == NULL) 644: return FALSE; 645: 646: if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx"))) 647: { 648: FreeLibrary (hModule); 649: return FALSE; 650: } 651: 652: wcscat (dir, L":\\"); 653: 654: FormatExResult = FALSE; 655: 1.1.1.12! root 656: // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS. 1.1.1.10 root 657: // It often helps to retry several times. 658: for (i = 0; i < 10 && FormatExResult != TRUE; i++) 659: { 1.1.1.11 root 660: FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback); 1.1.1.10 root 661: } 1.1.1.3 root 662: 663: FreeLibrary (hModule); 664: return FormatExResult; 665: } 666: 1.1.1.8 root 667: #endif 668: 1.1.1.12! root 669: BOOL WriteSector (void *dev, char *sector, 1.1.1.3 root 670: char *write_buf, int *write_buf_cnt, 1.1.1.8 root 671: __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) 1.1.1.3 root 672: { 1.1.1.8 root 673: static __int32 updateTime = 0; 1.1.1.12! root 674: UINT64_STRUCT unitNo; ! 675: ! 676: unitNo.Value = *nSecNo * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE; ! 677: ! 678: EncryptDataUnits (sector, &unitNo, SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo); 1.1.1.4 root 679: 1.1.1.12! root 680: (*nSecNo)++; 1.1.1.4 root 681: 1.1.1.3 root 682: memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE); 683: (*write_buf_cnt) += SECTOR_SIZE; 684: 685: if (*write_buf_cnt == WRITE_BUF_SIZE) 686: { 1.1.1.8 root 687: if ( 688: #ifdef _WIN32 689: _lwrite ((HFILE)dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR) 690: #else 691: fwrite (write_buf, 1, WRITE_BUF_SIZE, (FILE *)dev) != WRITE_BUF_SIZE) 692: #endif 1.1.1.3 root 693: return FALSE; 694: else 695: *write_buf_cnt = 0; 696: } 1.1.1.6 root 697: 1.1.1.8 root 698: #ifdef _WIN32 1.1.1.6 root 699: if (GetTickCount () - updateTime > 25) 1.1.1.3 root 700: { 1.1.1.6 root 701: if (UpdateProgressBar (*nSecNo)) 1.1.1.3 root 702: return FALSE; 1.1.1.6 root 703: 704: updateTime = GetTickCount (); 1.1.1.3 root 705: } 1.1.1.8 root 706: #else 707: UpdateProgressBar (*nSecNo); 708: #endif 1.1.1.3 root 709: 710: return TRUE; 711: 712: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.