|
|
1.1.1.10! root 1: /* ! 2: Legal Notice: The source code contained in this file has been derived from ! 3: the source code of Encryption for the Masses 2.02a, which is Copyright (c) ! 4: Paul Le Roux and which is covered by the 'License Agreement for Encryption ! 5: for the Masses'. Modifications and additions to that source code contained ! 6: in this file are Copyright (c) TrueCrypt Foundation and are covered by the ! 7: TrueCrypt License 2.2 the full text of which is contained in the file ! 8: License.txt included in TrueCrypt binary and source code distribution ! 9: packages. */ ! 10: ! 11: #include <stdlib.h> ! 12: #include <string.h> 1.1.1.6 root 13: 14: #include "Tcdefs.h" 15: 1.1.1.9 root 16: #include "Common.h" 1.1.1.6 root 17: #include "Crypto.h" 18: #include "Fat.h" 19: #include "Format.h" 1.1.1.9 root 20: #include "Random.h" 1.1.1.6 root 21: #include "Volumes.h" 1.1.1.8 root 22: 23: #ifdef _WIN32 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 root 31: int 1.1.1.10! root 32: 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; 49: PCRYPTO_INFO cryptoInfo; 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.10! root 59: char dosDev[TC_MAX_PATH] = { 0 }; ! 60: char devName[MAX_PATH] = { 0 }; ! 61: int driveLetter = -1; ! 62: WCHAR deviceName[MAX_PATH]; ! 63: 1.1.1.4 root 64: if (!hiddenVol) 65: size -= HEADER_SIZE; 1.1 root 66: 1.1.1.4 root 67: num_sectors = size / SECTOR_SIZE; 1.1.1.10! root 68: ! 69: if (bDevice) ! 70: { ! 71: strcpy ((char *)deviceName, volumePath); ! 72: ToUNICODE ((char *)deviceName); ! 73: ! 74: driveLetter = GetDiskDeviceDriveLetter (deviceName); ! 75: } ! 76: 1.1.1.3 root 77: VirtualLock (header, sizeof (header)); 1.1 root 78: 1.1.1.3 root 79: /* Copies any header structures into header, but does not do any 1.1 root 80: disk io */ 1.1.1.3 root 81: nStatus = VolumeWriteHeader (header, 1.1.1.7 root 82: ea, 83: LRW, // The only supported mode of operation when creating new volumes 1.1.1.6 root 84: password, 1.1 root 85: pkcs5, 86: 0, 87: 0, 1.1.1.4 root 88: &cryptoInfo, 1.1.1.6 root 89: hiddenVol ? size : 0, 90: FALSE); 1.1 root 91: 92: if (nStatus != 0) 1.1.1.3 root 93: { 94: burn (header, sizeof (header)); 95: VirtualUnlock (header, sizeof (header)); 1.1 root 96: return nStatus; 1.1.1.3 root 97: } 98: 1.1.1.6 root 99: if (bDevice) 1.1.1.3 root 100: { 1.1.1.10! root 101: /* Device-hosted volume */ ! 102: int nPass; ! 103: ! 104: if (FakeDosNameForDevice (volumePath, dosDev, devName, FALSE) != 0) 1.1.1.4 root 105: { 1.1.1.10! root 106: handleWin32Error (hwndDlg); ! 107: return ERR_DONT_REPORT; ! 108: } ! 109: ! 110: if (IsDeviceMounted (devName)) ! 111: { ! 112: if ((dev = DismountDrive (devName)) == INVALID_HANDLE_VALUE) 1.1.1.4 root 113: { 1.1.1.10! root 114: if (driveLetter > 2) // If a drive letter is assigned to the device, but not A:, B:, or C: 1.1.1.4 root 115: { 1.1.1.10! root 116: char rootPath[] = { driveLetter + 'A', ':', '\\', 0 }; ! 117: ! 118: // Remove the assigned drive letter so that dismount will have a higher chance of success ! 119: if (!DeleteVolumeMountPoint (rootPath)) ! 120: { ! 121: // Drive letter could not be removed ! 122: Error ("FORMAT_CANT_DISMOUNT_FILESYS"); ! 123: nStatus = ERR_DONT_REPORT; ! 124: goto error; ! 125: } ! 126: else ! 127: { ! 128: // Drive letter successfully removed, retry dismount ! 129: driveLetter = -1; ! 130: ! 131: if ((dev = DismountDrive (devName)) == INVALID_HANDLE_VALUE) ! 132: { ! 133: Error ("FORMAT_CANT_DISMOUNT_FILESYS_W_DRIVE_LETTER"); ! 134: nStatus = ERR_DONT_REPORT; ! 135: goto error; ! 136: } ! 137: } 1.1.1.4 root 138: } 1.1.1.10! root 139: else ! 140: { ! 141: Error ("FORMAT_CANT_DISMOUNT_FILESYS"); ! 142: nStatus = ERR_DONT_REPORT; ! 143: goto error; ! 144: } ! 145: } ! 146: } ! 147: else if (nCurrentOS == WIN_VISTA_OR_LATER && driveLetter == -1) ! 148: { ! 149: // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition ! 150: // to which no drive letter has been assigned under the system. This problem can be worked ! 151: // around by assigning a drive letter to the partition temporarily. ! 152: ! 153: char szDriveLetter[] = { 'A', ':', 0 }; ! 154: char rootPath[] = { 'A', ':', '\\', 0 }; ! 155: char uniqVolName[MAX_PATH+1] = { 0 }; ! 156: int tmpDriveLetter = -1; ! 157: BOOL bResult = FALSE; ! 158: ! 159: tmpDriveLetter = GetFirstAvailableDrive (); ! 160: ! 161: if (tmpDriveLetter != -1) ! 162: { ! 163: rootPath[0] += tmpDriveLetter; ! 164: szDriveLetter[0] += tmpDriveLetter; ! 165: ! 166: if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volumePath)) ! 167: { ! 168: bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH); ! 169: ! 170: DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE, ! 171: szDriveLetter, ! 172: volumePath); ! 173: ! 174: if (bResult ! 175: && SetVolumeMountPoint (rootPath, uniqVolName)) ! 176: { ! 177: // The drive letter can be removed immediately ! 178: DeleteVolumeMountPoint (rootPath); ! 179: } ! 180: } ! 181: } ! 182: } ! 183: ! 184: ! 185: // Perform open - 'quick format' - close - open to prevent Windows from restoring NTFS boot sector backup ! 186: for (nPass = 0; nPass < 2; nPass++) ! 187: { ! 188: // Try exclusive access mode first ! 189: if (dev == INVALID_HANDLE_VALUE) ! 190: dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); ! 191: ! 192: if (dev == INVALID_HANDLE_VALUE) ! 193: { ! 194: // Retry in shared mode ! 195: dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); ! 196: if (dev != INVALID_HANDLE_VALUE) ! 197: { ! 198: DWORD dwResult; ! 199: ! 200: if (IDNO == MessageBoxW (hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2)) ! 201: { ! 202: CloseHandle (dev); ! 203: dev = INVALID_HANDLE_VALUE; ! 204: nStatus = ERR_DONT_REPORT; ! 205: goto error; ! 206: } ! 207: ! 208: DeviceIoControl (dev, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL); ! 209: } ! 210: else ! 211: { ! 212: handleWin32Error (hwndDlg); ! 213: nStatus = ERR_DONT_REPORT; ! 214: goto error; ! 215: } ! 216: } ! 217: ! 218: if (hiddenVol) ! 219: break; // The following "quick format" operation would damage the outer volume ! 220: ! 221: if (nPass == 0) ! 222: { ! 223: char buf[65536]; ! 224: DWORD bw; ! 225: ! 226: // Pseudo "quick format" to prevent Windows from restoring NTFS boot sector backup ! 227: memset (buf, 0, sizeof (buf)); ! 228: WriteFile (dev, buf, sizeof (buf), &bw, NULL); ! 229: FlushFileBuffers (dev); ! 230: CloseHandle (dev); ! 231: dev = INVALID_HANDLE_VALUE; 1.1.1.4 root 232: } 233: } 1.1.1.3 root 234: } 235: else 236: { 1.1.1.10! root 237: /* File-hosted volume */ ! 238: 1.1.1.4 root 239: // We could support FILE_ATTRIBUTE_HIDDEN as an option 240: // (Now if the container has hidden or system file attribute, the OS will not allow 241: // overwritting it; so the user will have to delete it manually). 1.1.1.10! root 242: dev = CreateFile (volumePath, GENERIC_WRITE, 1.1.1.4 root 243: hiddenVol ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0, 244: NULL, hiddenVol ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); 1.1.1.6 root 245: 1.1.1.8 root 246: if (dev == INVALID_HANDLE_VALUE) 247: { 248: handleWin32Error (hwndDlg); 1.1.1.10! root 249: nStatus = ERR_DONT_REPORT; 1.1.1.8 root 250: goto error; 251: } 252: 1.1.1.6 root 253: if (!hiddenVol) 254: { 255: LARGE_INTEGER volumeSize; 1.1.1.8 root 256: volumeSize.QuadPart = size + HEADER_SIZE; 1.1.1.6 root 257: 1.1.1.8 root 258: if (sparseFileSwitch && quickFormat) 259: { 260: // Create as sparse file container 261: DWORD tmp; 262: if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL)) 263: { 264: handleWin32Error (hwndDlg); 1.1.1.10! root 265: nStatus = ERR_DONT_REPORT; 1.1.1.8 root 266: goto error; 267: } 268: } 269: 270: // Preallocate the file 1.1.1.6 root 271: if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN) 272: || !SetEndOfFile (dev) 273: || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0) 274: { 275: handleWin32Error (hwndDlg); 1.1.1.10! root 276: nStatus = ERR_DONT_REPORT; 1.1.1.7 root 277: goto error; 1.1.1.6 root 278: } 279: } 1.1.1.3 root 280: } 281: 1.1.1.6 root 282: if (hiddenVol && !bDevice && bPreserveTimestamp) 1.1.1.4 root 283: { 284: /* Remember the container timestamp (used to reset file date and time of file-hosted 285: containers to preserve plausible deniability of hidden volume) */ 286: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) 287: { 288: bTimeStampValid = FALSE; 1.1.1.6 root 289: MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); 1.1.1.4 root 290: } 291: else 292: bTimeStampValid = TRUE; 1.1.1.3 root 293: } 1.1 root 294: 295: KillTimer (hwndDlg, 0xff); 296: 1.1.1.6 root 297: /* Volume header */ 1.1.1.4 root 298: 299: // Hidden volume setup 300: if (hiddenVol) 301: { 302: // Check hidden volume size 303: if (hiddenVolHostSize < MIN_HIDDEN_VOLUME_HOST_SIZE || hiddenVolHostSize > MAX_HIDDEN_VOLUME_HOST_SIZE) 304: { 1.1.1.7 root 305: nStatus = ERR_VOL_SIZE_WRONG; 306: goto error; 1.1.1.4 root 307: } 308: 309: // Seek to hidden volume header location 310: if (!SeekHiddenVolHeader ((HFILE) dev, hiddenVolHostSize, bDevice)) 311: { 1.1.1.7 root 312: nStatus = ERR_VOL_SEEKING; 313: goto error; 1.1.1.4 root 314: } 315: 316: } 317: 318: // Write the volume header 1.1.1.8 root 319: if (_lwrite ((HFILE) dev, header, HEADER_SIZE) == HFILE_ERROR) 1.1.1.10! root 320: { ! 321: handleWin32Error (hwndDlg); ! 322: nStatus = ERR_DONT_REPORT; ! 323: goto error; ! 324: } 1.1.1.4 root 325: 1.1.1.6 root 326: /* Data area */ 1.1.1.4 root 327: 1.1.1.10! root 328: startSector = HEADER_SIZE / SECTOR_SIZE; // Data area of normal volume starts right after volume header 1.1.1.4 root 329: 330: if (hiddenVol) 331: { 332: // Calculate data area position of hidden volume 333: unsigned __int64 startOffset = hiddenVolHostSize - size - HIDDEN_VOL_HEADER_OFFSET; 1.1.1.7 root 334: cryptoInfo->hiddenVolumeOffset = startOffset; 1.1.1.4 root 335: 336: // Validate the offset 337: if (startOffset % SECTOR_SIZE != 0) 338: { 1.1.1.6 root 339: nStatus = ERR_VOL_SIZE_WRONG; 340: goto error; 1.1.1.4 root 341: } 342: 343: startSector = startOffset / SECTOR_SIZE; 344: quickFormat = TRUE; // To entirely format a hidden volume would be redundant 345: } 346: 347: // Format filesystem 348: 1.1.1.3 root 349: switch (fileSystem) 350: { 351: case FILESYS_NONE: 1.1.1.10! root 352: case FILESYS_NTFS: 1.1.1.8 root 353: nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, quickFormat); 1.1.1.3 root 354: break; 1.1.1.10! root 355: 1.1.1.3 root 356: case FILESYS_FAT: 1.1.1.4 root 357: if (num_sectors > 0xFFFFffff) 358: { 1.1.1.6 root 359: nStatus = ERR_VOL_SIZE_WRONG; 360: goto error; 1.1.1.4 root 361: } 362: 363: // Calculate the fats, root dir etc 364: ft.num_sectors = (unsigned int) (num_sectors); 365: ft.cluster_size = clusterSize; 1.1.1.6 root 366: memcpy (ft.volume_name, "NO NAME ", 11); 1.1.1.4 root 367: GetFatParams (&ft); 368: *realClusterSize = ft.cluster_size * SECTOR_SIZE; 369: 1.1.1.8 root 370: nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, quickFormat); 1.1.1.3 root 371: break; 372: } 1.1 root 373: 1.1.1.10! root 374: if (bDevice && nStatus == 0 ! 375: && driveLetter > 1) // If a drive letter is assigned to the device, but not A: or B: ! 376: { ! 377: char rootPath[] = { driveLetter + 'A', ':', '\\', 0 }; ! 378: ! 379: // The device has been successfully formatted so we should remove its original drive letter (inexperienced ! 380: // users often attempt to double click the original drive letter and due to the Windows format prompt ! 381: // they sometimes format the volume, which disables encryption without them realizing it). ! 382: DeleteVolumeMountPoint (rootPath); ! 383: } 1.1.1.4 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: 391: crypto_close (cryptoInfo); 1.1.1.4 root 392: 393: if (bTimeStampValid) 394: { 395: // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 396: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) 1.1.1.6 root 397: MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); 398: } 399: 400: if (!bDevice && !hiddenVol && nStatus != 0) 401: { 402: // Remove preallocated part before closing file handle if format failed 403: if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0) 404: SetEndOfFile (dev); 1.1.1.4 root 405: } 406: 1.1.1.3 root 407: CloseHandle (dev); 1.1.1.10! root 408: dev = INVALID_HANDLE_VALUE; 1.1 root 409: 1.1.1.10! root 410: if (dosDev[0]) ! 411: RemoveFakeDosName (volumePath, dosDev); 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); ! 416: return nStatus; ! 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.10! root 433: return ERR_NO_FREE_DRIVES; ! 434: } 1.1.1.4 root 435: 1.1.1.10! root 436: mountOptions.ReadOnly = FALSE; ! 437: mountOptions.Removable = FALSE; ! 438: mountOptions.ProtectHiddenVolume = FALSE; ! 439: mountOptions.PreserveTimestamp = bPreserveTimestamp; 1.1.1.3 root 440: 1.1.1.10! root 441: if (MountVolume (hwndDlg, driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) ! 442: { ! 443: MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND); ! 444: MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); ! 445: return ERR_VOL_MOUNT_FAILED; ! 446: } 1.1.1.3 root 447: 1.1.1.10! root 448: if (!IsAdmin () && IsUacSupported ()) ! 449: retCode = UacFormatNtfs (hwndDlg, driveNo, clusterSize); ! 450: else ! 451: retCode = FormatNtfs (driveNo, clusterSize); 1.1.1.3 root 452: 1.1.1.10! root 453: if (retCode != TRUE) ! 454: { ! 455: if (!UnmountVolume (hwndDlg, driveNo, FALSE)) ! 456: MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); 1.1.1.3 root 457: 1.1.1.10! root 458: Error ("FORMAT_NTFS_FAILED"); ! 459: return ERR_DONT_REPORT; 1.1.1.3 root 460: } 1.1.1.10! root 461: ! 462: if (!UnmountVolume (hwndDlg, driveNo, FALSE)) ! 463: MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); 1.1.1.3 root 464: } 465: 1.1 root 466: return nStatus; 1.1.1.3 root 467: } 1.1 root 468: 1.1.1.8 root 469: #endif 1.1.1.3 root 470: 1.1.1.8 root 471: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) 1.1.1.3 root 472: { 473: int write_buf_cnt = 0; 474: char sector[SECTOR_SIZE], *write_buf; 1.1.1.4 root 475: unsigned __int64 nSecNo = startSector; 1.1.1.6 root 476: int retVal; 1.1.1.7 root 477: char temporaryKey[DISKKEY_SIZE]; 1.1.1.4 root 478: 1.1.1.8 root 479: #ifdef _WIN32 480: LARGE_INTEGER startOffset; 481: LARGE_INTEGER newOffset; 482: 1.1.1.4 root 483: // Seek to start sector 484: startOffset.QuadPart = startSector * SECTOR_SIZE; 1.1.1.6 root 485: if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) 486: || newOffset.QuadPart != startOffset.QuadPart) 1.1.1.4 root 487: { 488: return ERR_VOL_SEEKING; 489: } 1.1.1.8 root 490: #endif 1.1.1.3 root 491: 1.1.1.8 root 492: write_buf = (char *) TCalloc (WRITE_BUF_SIZE); 1.1.1.3 root 493: memset (sector, 0, sizeof (sector)); 494: 1.1.1.7 root 495: /* Fill the rest of the data area with random data */ 496: 1.1.1.3 root 497: if(!quickFormat) 498: { 1.1.1.7 root 499: /* Generate a random temporary key set to be used for "dummy" encryption that will fill 500: the free disk space (data area) with random data. This is necessary for plausible 501: deniability of hidden volumes (and also reduces the amount of predictable plaintext 502: within the volume). */ 1.1.1.6 root 503: 1.1.1.9 root 504: // Temporary master key 505: if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) 506: goto fail; 507: // Secondary key (LRW mode) 508: if (!RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv, FALSE)) 509: goto fail; 1.1.1.7 root 510: 511: retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); 1.1.1.6 root 512: if (retVal != 0) 1.1.1.7 root 513: { 514: burn (temporaryKey, sizeof(temporaryKey)); 1.1.1.6 root 515: return retVal; 1.1.1.7 root 516: } 517: if (!EAInitMode (cryptoInfo)) 518: { 519: burn (temporaryKey, sizeof(temporaryKey)); 520: return ERR_MODE_INIT_FAILED; 521: } 1.1.1.4 root 522: 1.1.1.3 root 523: while (num_sectors--) 524: { 1.1.1.7 root 525: /* Generate random plaintext. Note that reused plaintext blocks are not a concern 526: here since LRW mode is designed to hide patterns. Furthermore, patterns in plaintext 527: do occur commonly on media in the "real world", so it might actually be a fatal 528: mistake to try to avoid them completely. */ 1.1.1.9 root 529: 530: #if RNG_POOL_SIZE > SECTOR_SIZE 531: #error RNG_POOL_SIZE > SECTOR_SIZE 1.1.1.7 root 532: #endif 533: 1.1.1.9 root 534: #ifdef _WIN32 535: if (!RandpeekBytes (sector, RNG_POOL_SIZE) 536: || !RandpeekBytes (sector + RNG_POOL_SIZE, SECTOR_SIZE - RNG_POOL_SIZE)) 537: goto fail; 538: #else 539: if ((nSecNo & 0x3fff) == 0) 540: { 541: if (!RandgetBytes (sector, RNG_POOL_SIZE, FALSE) 542: || !RandgetBytes (sector + RNG_POOL_SIZE, SECTOR_SIZE - RNG_POOL_SIZE, FALSE)) 543: goto fail; 544: } 545: #endif 1.1.1.7 root 546: // Encrypt the random plaintext and write it to the disk 1.1.1.6 root 547: if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, 1.1.1.8 root 548: cryptoInfo) == FALSE) 1.1.1.3 root 549: goto fail; 550: } 1.1.1.8 root 551: if (write_buf_cnt != 0 && 552: #ifdef _WIN32 553: _lwrite ((HFILE)dev, write_buf, write_buf_cnt) == HFILE_ERROR) 554: #else 555: fwrite (write_buf, 1, write_buf_cnt, (FILE *)dev) != (size_t)write_buf_cnt) 556: #endif 1.1.1.3 root 557: goto fail; 558: } 559: else 560: nSecNo = num_sectors; 561: 562: UpdateProgressBar (nSecNo); 563: 564: TCfree (write_buf); 1.1.1.7 root 565: burn (temporaryKey, sizeof(temporaryKey)); 1.1.1.3 root 566: return 0; 567: 568: fail: 569: 570: TCfree (write_buf); 1.1.1.7 root 571: burn (temporaryKey, sizeof(temporaryKey)); 1.1.1.3 root 572: return ERR_OS_ERROR; 1.1 root 573: } 1.1.1.3 root 574: 1.1.1.8 root 575: #ifdef _WIN32 1.1.1.3 root 576: 577: volatile BOOLEAN FormatExResult; 578: 579: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter) 580: { 581: if (command == FMIFS_DONE) 582: FormatExResult = *(BOOLEAN *) parameter; 583: return TRUE; 584: } 585: 586: BOOL FormatNtfs (int driveNo, int clusterSize) 587: { 588: WCHAR dir[8] = { driveNo + 'A', 0 }; 589: PFORMATEX FormatEx; 590: HMODULE hModule = LoadLibrary ("fmifs.dll"); 1.1.1.10! root 591: int i; 1.1.1.3 root 592: 593: if (hModule == NULL) 594: return FALSE; 595: 596: if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx"))) 597: { 598: FreeLibrary (hModule); 599: return FALSE; 600: } 601: 602: wcscat (dir, L":\\"); 603: 604: FormatExResult = FALSE; 605: 1.1.1.10! root 606: // Windows sometimes fail to format a volume (hosted on a removable medium) as NTFS. ! 607: // It often helps to retry several times. ! 608: for (i = 0; i < 10 && FormatExResult != TRUE; i++) ! 609: { 1.1.1.3 root 610: FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * 512, FormatExCallback); 1.1.1.10! root 611: } 1.1.1.3 root 612: 613: FreeLibrary (hModule); 614: return FormatExResult; 615: } 616: 1.1.1.8 root 617: #endif 618: 1.1.1.3 root 619: BOOL 1.1.1.8 root 620: WriteSector (void *dev, char *sector, 1.1.1.3 root 621: char *write_buf, int *write_buf_cnt, 1.1.1.8 root 622: __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) 1.1.1.3 root 623: { 1.1.1.8 root 624: static __int32 updateTime = 0; 1.1.1.4 root 625: 1.1.1.6 root 626: EncryptSectors ((unsigned __int32 *) sector, 1.1.1.7 root 627: (*nSecNo)++, 1, cryptoInfo); 1.1.1.4 root 628: 1.1.1.3 root 629: memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE); 630: (*write_buf_cnt) += SECTOR_SIZE; 631: 632: if (*write_buf_cnt == WRITE_BUF_SIZE) 633: { 1.1.1.8 root 634: if ( 635: #ifdef _WIN32 636: _lwrite ((HFILE)dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR) 637: #else 638: fwrite (write_buf, 1, WRITE_BUF_SIZE, (FILE *)dev) != WRITE_BUF_SIZE) 639: #endif 1.1.1.3 root 640: return FALSE; 641: else 642: *write_buf_cnt = 0; 643: } 1.1.1.6 root 644: 1.1.1.8 root 645: #ifdef _WIN32 1.1.1.6 root 646: if (GetTickCount () - updateTime > 25) 1.1.1.3 root 647: { 1.1.1.6 root 648: if (UpdateProgressBar (*nSecNo)) 1.1.1.3 root 649: return FALSE; 1.1.1.6 root 650: 651: updateTime = GetTickCount (); 1.1.1.3 root 652: } 1.1.1.8 root 653: #else 654: UpdateProgressBar (*nSecNo); 655: #endif 1.1.1.3 root 656: 657: return TRUE; 658: 659: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.