|
|
1.1 root 1: /* 1.1.1.8 ! root 2: Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.6 root 4: Governed by the TrueCrypt License 2.6 the full text of which is contained 1.1 root 5: in the file License.txt included in TrueCrypt binary and source code 6: distribution packages. 7: */ 8: 9: #include "Tcdefs.h" 10: #include "Platform/Finally.h" 11: #include "Platform/ForEach.h" 12: #include <Setupapi.h> 13: #include <devguid.h> 14: #include <io.h> 15: #include <shlobj.h> 16: #include <atlbase.h> 17: #include "BootEncryption.h" 18: #include "Boot/Windows/BootCommon.h" 19: #include "Common/Resource.h" 20: #include "Crc.h" 21: #include "Crypto.h" 22: #include "Dlgcode.h" 23: #include "Endian.h" 1.1.1.5 root 24: #include "Language.h" 1.1 root 25: #include "Random.h" 26: #include "Registry.h" 27: #include "Volumes.h" 28: 29: #ifdef VOLFORMAT 30: #include "Format/FormatCom.h" 31: #elif defined (TCMOUNT) 32: #include "Mount/MainCom.h" 33: #endif 34: 35: namespace TrueCrypt 36: { 37: #if !defined (SETUP) 38: 39: class Elevator 40: { 41: public: 1.1.1.6 root 42: 43: static void AddReference () 44: { 45: ++ReferenceCount; 46: } 47: 48: 1.1 root 49: static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) 50: { 51: Elevate(); 52: 53: CComBSTR inputBstr; 54: if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK) 55: throw ParameterIncorrect (SRC_POS); 56: 57: CComBSTR outputBstr; 58: if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK) 59: throw ParameterIncorrect (SRC_POS); 60: 61: DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr); 1.1.1.5 root 62: 63: if (output) 64: memcpy (output, *(void **) &outputBstr, outputSize); 65: 1.1 root 66: if (result != ERROR_SUCCESS) 67: { 68: SetLastError (result); 69: throw SystemException(); 70: } 71: } 72: 73: static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) 74: { 75: Elevate(); 76: 77: CComBSTR bufferBstr; 78: if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK) 79: throw ParameterIncorrect (SRC_POS); 80: DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone); 81: 82: if (result != ERROR_SUCCESS) 83: { 84: SetLastError (result); 85: throw SystemException(); 86: } 87: 88: if (!write) 89: memcpy (buffer, (BYTE *) bufferBstr.m_str, size); 90: } 91: 1.1.1.6 root 92: static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) 1.1.1.5 root 93: { 94: Elevate(); 95: 1.1.1.6 root 96: return ElevatedComInstance->IsPagingFileActive (checkNonWindowsPartitionsOnly); 1.1.1.5 root 97: } 98: 99: static void WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) 1.1 root 100: { 101: Elevate(); 102: 1.1.1.5 root 103: DWORD result = ElevatedComInstance->WriteLocalMachineRegistryDwordValue (CComBSTR (keyPath), CComBSTR (valueName), value); 104: 105: if (result != ERROR_SUCCESS) 106: { 107: SetLastError (result); 108: throw SystemException(); 109: } 110: } 111: 112: static void RegisterFilterDriver (bool registerDriver, bool volumeClass) 113: { 114: Elevate(); 115: 116: DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE, volumeClass ? TRUE : FALSE); 1.1 root 117: if (result != ERROR_SUCCESS) 118: { 119: SetLastError (result); 120: throw SystemException(); 121: } 122: } 123: 1.1.1.6 root 124: 1.1 root 125: static void Release () 126: { 1.1.1.6 root 127: if (--ReferenceCount == 0 && ElevatedComInstance) 1.1 root 128: { 129: ElevatedComInstance->Release(); 130: ElevatedComInstance = nullptr; 131: CoUninitialize (); 132: } 133: } 134: 135: static void SetDriverServiceStartType (DWORD startType) 136: { 137: Elevate(); 138: 139: DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType); 140: if (result != ERROR_SUCCESS) 141: { 142: SetLastError (result); 143: throw SystemException(); 144: } 145: } 146: 147: protected: 148: static void Elevate () 149: { 150: if (IsAdmin()) 151: { 152: SetLastError (ERROR_ACCESS_DENIED); 153: throw SystemException(); 154: } 155: 1.1.1.5 root 156: if (!ElevatedComInstance || ElevatedComInstanceThreadId != GetCurrentThreadId()) 1.1 root 157: { 158: CoInitialize (NULL); 159: ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg); 1.1.1.5 root 160: ElevatedComInstanceThreadId = GetCurrentThreadId(); 1.1 root 161: } 162: } 163: 164: #if defined (TCMOUNT) 165: static ITrueCryptMainCom *ElevatedComInstance; 166: #elif defined (VOLFORMAT) 167: static ITrueCryptFormatCom *ElevatedComInstance; 168: #endif 1.1.1.5 root 169: static DWORD ElevatedComInstanceThreadId; 1.1.1.6 root 170: static int ReferenceCount; 1.1 root 171: }; 172: 173: #if defined (TCMOUNT) 174: ITrueCryptMainCom *Elevator::ElevatedComInstance; 175: #elif defined (VOLFORMAT) 176: ITrueCryptFormatCom *Elevator::ElevatedComInstance; 177: #endif 1.1.1.5 root 178: DWORD Elevator::ElevatedComInstanceThreadId; 1.1.1.6 root 179: int Elevator::ReferenceCount = 0; 1.1 root 180: 181: #else // SETUP 182: 183: class Elevator 184: { 185: public: 1.1.1.6 root 186: static void AddReference () { } 1.1 root 187: static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); } 188: static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); } 1.1.1.5 root 189: static void RegisterFilterDriver (bool registerDriver, bool volumeClass) { throw ParameterIncorrect (SRC_POS); } 1.1 root 190: static void Release () { } 191: static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); } 192: }; 193: 194: #endif // SETUP 195: 196: 197: File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false) 198: { 199: Handle = CreateFile (path.c_str(), 1.1.1.6 root 200: readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, 1.1 root 201: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING, 202: FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); 203: 204: try 205: { 206: throw_sys_if (Handle == INVALID_HANDLE_VALUE); 207: } 208: catch (SystemException &) 209: { 210: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) 211: Elevated = true; 212: else 213: throw; 214: } 215: 216: FileOpen = true; 217: FilePointerPosition = 0; 218: IsDevice = false; 219: Path = path; 220: } 221: 222: void File::Close () 223: { 224: if (FileOpen) 225: { 226: if (!Elevated) 227: CloseHandle (Handle); 228: 229: FileOpen = false; 230: } 231: } 232: 233: DWORD File::Read (byte *buffer, DWORD size) 234: { 235: DWORD bytesRead; 236: 237: if (Elevated) 238: { 239: DWORD bytesRead; 240: 241: Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead); 242: FilePointerPosition += bytesRead; 243: return bytesRead; 244: } 245: 246: throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL)); 247: return bytesRead; 248: } 249: 250: void File::SeekAt (int64 position) 251: { 1.1.1.6 root 252: FilePointerPosition = position; 253: 254: if (!Elevated) 1.1 root 255: { 256: LARGE_INTEGER pos; 257: pos.QuadPart = position; 258: throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN)); 259: } 260: } 261: 262: void File::Write (byte *buffer, DWORD size) 263: { 264: DWORD bytesWritten; 1.1.1.6 root 265: 266: try 1.1 root 267: { 1.1.1.6 root 268: if (Elevated) 269: { 270: Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten); 271: FilePointerPosition += bytesWritten; 272: throw_sys_if (bytesWritten != size); 273: } 274: else 275: { 276: throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size); 277: } 1.1 root 278: } 1.1.1.6 root 279: catch (SystemException &e) 1.1 root 280: { 1.1.1.6 root 281: if (!IsDevice || e.ErrorCode != ERROR_WRITE_PROTECT || !IsHiddenOSRunning()) 282: throw; 283: 284: BootEncryption bootEnc (NULL); 285: 286: while (size >= SECTOR_SIZE) 287: { 288: bootEnc.WriteBootDriveSector (FilePointerPosition, buffer); 289: 290: FilePointerPosition += SECTOR_SIZE; 291: buffer += SECTOR_SIZE; 292: size -= SECTOR_SIZE; 293: } 1.1 root 294: } 295: } 296: 297: void Show (HWND parent, const string &str) 298: { 299: MessageBox (parent, str.c_str(), NULL, 0); 300: } 301: 302: 303: Device::Device (string path, bool readOnly) 304: { 305: FileOpen = false; 306: Elevated = false; 307: 308: Handle = CreateFile ((string ("\\\\.\\") + path).c_str(), 1.1.1.6 root 309: readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, 1.1 root 310: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 311: FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); 312: 313: try 314: { 315: throw_sys_if (Handle == INVALID_HANDLE_VALUE); 316: } 317: catch (SystemException &) 318: { 319: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) 320: Elevated = true; 321: else 322: throw; 323: } 324: 325: FileOpen = true; 326: FilePointerPosition = 0; 327: IsDevice = true; 328: Path = path; 329: } 330: 331: 1.1.1.6 root 332: BootEncryption::BootEncryption (HWND parent) 333: : DriveConfigValid (false), 334: ParentWindow (parent), 335: RealSystemDriveSizeValid (false), 336: RescueIsoImage (nullptr), 337: RescueVolumeHeaderValid (false), 338: SelectedEncryptionAlgorithmId (0), 339: VolumeHeaderValid (false) 340: { 341: Elevator::AddReference(); 342: } 343: 344: 1.1 root 345: BootEncryption::~BootEncryption () 346: { 347: if (RescueIsoImage) 348: delete RescueIsoImage; 349: 350: Elevator::Release(); 351: } 352: 353: 354: void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) 355: { 356: try 357: { 358: DWORD bytesReturned; 359: throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL)); 360: } 361: catch (SystemException &) 362: { 363: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) 364: Elevator::CallDriver (ioctl, input, inputSize, output, outputSize); 365: else 366: throw; 367: } 368: } 369: 370: 1.1.1.5 root 371: // Finds the first partition physically located behind the active one and returns its properties 372: Partition BootEncryption::GetPartitionForHiddenOS () 373: { 374: Partition candidatePartition; 375: 376: memset (&candidatePartition, 0, sizeof(candidatePartition)); 377: 378: // The user may have modified/added/deleted partitions since the time the partition table was last scanned 379: InvalidateCachedSysDriveProperties(); 380: 381: SystemDriveConfiguration config = GetSystemDriveConfiguration (); 382: bool activePartitionFound = false; 383: bool candidateForHiddenOSFound = false; 384: 385: if (config.SystemPartition.IsGPT) 386: throw ParameterIncorrect (SRC_POS); // It is assumed that CheckRequirements() had been called 387: 388: // Find the first active partition on the system drive 389: foreach (const Partition &partition, config.Partitions) 390: { 391: if (partition.Info.BootIndicator) 392: { 393: if (partition.Info.PartitionNumber != config.SystemPartition.Number) 394: { 395: throw ErrorException (wstring (GetString ("SYSTEM_PARTITION_NOT_ACTIVE")) 396: + GetRemarksOnHiddenOS()); 397: } 398: 399: activePartitionFound = true; 400: break; 401: } 402: } 403: 404: /* WARNING: Note that the partition number at the end of a device path (\Device\HarddiskY\PartitionX) must 405: NOT be used to find the first partition physically located behind the active one. The reason is that the 406: user may have deleted and created partitions during this session and e.g. the second partition could have 407: a higer number than the third one. */ 408: 409: 410: // Find the first partition physically located behind the active partition 411: if (activePartitionFound) 412: { 413: int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart; 414: 415: foreach (const Partition &partition, config.Partitions) 416: { 417: if (partition.Info.StartingOffset.QuadPart > config.SystemPartition.Info.StartingOffset.QuadPart 418: && partition.Info.StartingOffset.QuadPart < minOffsetFound) 419: { 420: minOffsetFound = partition.Info.StartingOffset.QuadPart; 421: 422: candidatePartition = partition; 423: 424: candidateForHiddenOSFound = true; 425: } 426: } 427: 428: if (!candidateForHiddenOSFound) 429: { 430: throw ErrorException (wstring (GetString ("NO_PARTITION_FOLLOWS_BOOT_PARTITION")) 431: + GetRemarksOnHiddenOS()); 432: } 433: 434: if (config.SystemPartition.Info.PartitionLength.QuadPart > TC_MAX_FAT_FS_SIZE) 435: { 436: if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS) 437: { 438: throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS_NTFS")) 439: + GetRemarksOnHiddenOS()); 440: } 441: } 442: else if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT) 443: { 444: throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS")) 445: + GetRemarksOnHiddenOS()); 446: } 447: } 448: else 449: { 450: // No active partition on the system drive 451: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); 452: } 453: 1.1.1.6 root 454: HiddenOSCandidatePartition = candidatePartition; 1.1.1.5 root 455: return candidatePartition; 456: } 457: 458: 1.1 root 459: DWORD BootEncryption::GetDriverServiceStartType () 460: { 461: DWORD startType; 462: throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType)); 463: return startType; 464: } 465: 466: 1.1.1.5 root 467: wstring BootEncryption::GetRemarksOnHiddenOS () 468: { 469: return (wstring (L"\n\n") 470: + GetString ("TWO_SYSTEMS_IN_ONE_PARTITION_REMARK") 471: + L"\n\n" 472: + GetString ("FOR_MORE_INFO_ON_PARTITIONS")); 473: } 474: 475: 1.1 root 476: void BootEncryption::SetDriverServiceStartType (DWORD startType) 477: { 478: if (!IsAdmin() && IsUacSupported()) 479: { 480: Elevator::SetDriverServiceStartType (startType); 481: return; 482: } 483: 484: BOOL startOnBoot = (startType == SERVICE_BOOT_START); 485: 486: SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); 487: throw_sys_if (!serviceManager); 488: 489: finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); }); 490: 491: SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG); 492: throw_sys_if (!service); 493: 494: finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); }); 495: 1.1.1.5 root 496: // Windows versions preceding Vista can be installed on FAT filesystem which does not 497: // support long filenames during boot. Convert the driver path to short form if required. 498: string driverPath; 1.1.1.8 ! root 499: if (startOnBoot && !IsOSAtLeast (WIN_VISTA)) 1.1.1.5 root 500: { 501: char pathBuf[MAX_PATH]; 502: char filesystem[128]; 503: 504: string path (GetWindowsDirectory()); 505: path += "\\drivers\\truecrypt.sys"; 506: 507: if (GetVolumePathName (path.c_str(), pathBuf, sizeof (pathBuf)) 508: && GetVolumeInformation (pathBuf, NULL, 0, NULL, NULL, NULL, filesystem, sizeof(filesystem)) 509: && memcmp (filesystem, "FAT", 3) == 0) 510: { 511: throw_sys_if (GetShortPathName (path.c_str(), pathBuf, sizeof (pathBuf)) == 0); 512: 513: // Convert absolute path to relative to the Windows directory 514: driverPath = pathBuf; 515: driverPath = driverPath.substr (driverPath.rfind ("\\", driverPath.rfind ("\\", driverPath.rfind ("\\") - 1) - 1) + 1); 516: 517: if (Is64BitOs()) 518: driverPath = "SysWOW64" + driverPath.substr (driverPath.find ("\\")); 519: } 520: } 521: 1.1 root 522: throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 1.1.1.5 root 523: startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, 524: driverPath.empty() ? NULL : driverPath.c_str(), 1.1 root 525: startOnBoot ? "Filter" : NULL, 526: NULL, NULL, NULL, NULL, NULL)); 527: 528: // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER 529: throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType)); 530: } 531: 532: 533: void BootEncryption::ProbeRealSystemDriveSize () 534: { 535: if (RealSystemDriveSizeValid) 536: return; 537: 538: GetSystemDriveConfiguration(); 539: 540: ProbeRealDriveSizeRequest request; 541: _snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str()); 542: 543: CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request)); 544: DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize; 545: 1.1.1.5 root 546: RealSystemDriveSizeValid = true; 1.1.1.3 root 547: 548: if (request.TimeOut) 549: throw TimeOut (SRC_POS); 1.1 root 550: } 551: 552: 1.1.1.5 root 553: void BootEncryption::InvalidateCachedSysDriveProperties () 554: { 555: DriveConfigValid = false; 556: RealSystemDriveSizeValid = false; 557: } 558: 559: 1.1 root 560: PartitionList BootEncryption::GetDrivePartitions (int driveNumber) 561: { 562: PartitionList partList; 563: 564: for (int partNumber = 0; partNumber < 64; ++partNumber) 565: { 566: stringstream partPath; 567: partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber; 568: 569: DISK_PARTITION_INFO_STRUCT diskPartInfo; 570: _snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str()); 571: 572: try 573: { 574: CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo)); 575: } 576: catch (...) 577: { 578: continue; 579: } 580: 581: Partition part; 582: part.DevicePath = partPath.str(); 583: part.Number = partNumber; 584: part.Info = diskPartInfo.partInfo; 585: part.IsGPT = diskPartInfo.IsGPT; 586: 587: // Mount point 588: wstringstream ws; 589: ws << partPath.str().c_str(); 590: int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); 591: 592: if (driveNumber >= 0) 593: { 594: part.MountPoint += (char) (driveNumber + 'A'); 595: part.MountPoint += ":"; 596: } 1.1.1.8 ! root 597: ! 598: // Volume ID ! 599: wchar_t volumePath[TC_MAX_PATH]; ! 600: if (ResolveSymbolicLink ((wchar_t *) ws.str().c_str(), volumePath)) ! 601: { ! 602: wchar_t volumeName[TC_MAX_PATH]; ! 603: HANDLE fh = FindFirstVolumeW (volumeName, array_capacity (volumeName)); ! 604: if (fh != INVALID_HANDLE_VALUE) ! 605: { ! 606: do ! 607: { ! 608: wstring volumeNameStr = volumeName; ! 609: wchar_t devicePath[TC_MAX_PATH]; ! 610: ! 611: if (QueryDosDeviceW (volumeNameStr.substr (4, volumeNameStr.size() - 1 - 4).c_str(), devicePath, array_capacity (devicePath)) != 0 ! 612: && wcscmp (volumePath, devicePath) == 0) ! 613: { ! 614: part.VolumeNameId = volumeName; ! 615: break; ! 616: } ! 617: ! 618: } while (FindNextVolumeW (fh, volumeName, array_capacity (volumeName))); ! 619: ! 620: FindVolumeClose (fh); ! 621: } ! 622: } ! 623: 1.1 root 624: partList.push_back (part); 625: } 626: 627: return partList; 628: } 629: 630: 631: DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber) 632: { 633: stringstream devName; 634: devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; 635: 636: DISK_GEOMETRY geometry; 637: throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry)); 638: return geometry; 639: } 640: 641: 642: string BootEncryption::GetWindowsDirectory () 643: { 644: char buf[MAX_PATH]; 1.1.1.5 root 645: throw_sys_if (GetSystemDirectory (buf, sizeof (buf)) == 0); 646: 647: return string (buf); 1.1 root 648: } 1.1.1.6 root 649: 650: 651: string BootEncryption::GetTempPath () 652: { 653: char tempPath[MAX_PATH]; 654: DWORD tempLen = ::GetTempPath (sizeof (tempPath), tempPath); 655: if (tempLen == 0 || tempLen > sizeof (tempPath)) 656: throw ParameterIncorrect (SRC_POS); 657: 658: return string (tempPath); 659: } 660: 1.1 root 661: 662: uint16 BootEncryption::GetInstalledBootLoaderVersion () 663: { 664: uint16 version; 665: CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version)); 666: return version; 667: } 668: 669: 1.1.1.3 root 670: // Note that this does not require admin rights (it just requires the driver to be running) 671: bool BootEncryption::IsBootLoaderOnDrive (char *devicePath) 672: { 673: try 674: { 675: OPEN_TEST_STRUCT openTestStruct; 1.1.1.8 ! root 676: memset (&openTestStruct, 0, sizeof (openTestStruct)); 1.1.1.3 root 677: DWORD dwResult; 678: 679: strcpy ((char *) &openTestStruct.wszFileName[0], devicePath); 680: ToUNICODE ((char *) &openTestStruct.wszFileName[0]); 681: 682: openTestStruct.bDetectTCBootLoader = TRUE; 683: 684: return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, 685: &openTestStruct, sizeof (OPEN_TEST_STRUCT), 1.1.1.8 ! root 686: &openTestStruct, sizeof (OPEN_TEST_STRUCT), ! 687: &dwResult, NULL) && openTestStruct.TCBootLoaderDetected); 1.1.1.3 root 688: } 689: catch (...) 690: { 691: return false; 692: } 693: } 694: 695: 1.1 root 696: BootEncryptionStatus BootEncryption::GetStatus () 697: { 698: /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */ 699: 700: BootEncryptionStatus status; 701: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status)); 702: return status; 703: } 704: 705: 706: void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties) 707: { 708: if (properties == NULL) 709: throw ParameterIncorrect (SRC_POS); 710: 711: CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties)); 712: } 713: 714: 1.1.1.5 root 715: bool BootEncryption::IsHiddenSystemRunning () 716: { 717: int hiddenSystemStatus; 718: 719: CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus)); 720: return hiddenSystemStatus != 0; 721: } 722: 723: 1.1.1.2 root 724: bool BootEncryption::SystemDriveContainsPartitionType (byte type) 725: { 726: Device device (GetSystemDriveConfiguration().DevicePath, true); 727: 728: byte mbrBuf[SECTOR_SIZE]; 729: device.SeekAt (0); 730: device.Read (mbrBuf, sizeof (mbrBuf)); 731: 732: MBR *mbr = reinterpret_cast <MBR *> (mbrBuf); 733: if (mbr->Signature != 0xaa55) 734: throw ParameterIncorrect (SRC_POS); 735: 736: for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i) 737: { 738: if (mbr->Partitions[i].Type == type) 739: return true; 740: } 741: 742: return false; 743: } 744: 745: 746: bool BootEncryption::SystemDriveContainsExtendedPartition () 747: { 748: return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED); 749: } 750: 751: 752: bool BootEncryption::SystemDriveIsDynamic () 753: { 1.1.1.5 root 754: GetSystemDriveConfigurationRequest request; 755: _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); 756: 757: CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); 758: return request.DriveIsDynamic ? true : false; 1.1.1.2 root 759: } 760: 761: 1.1 root 762: SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration () 763: { 764: if (DriveConfigValid) 765: return DriveConfig; 766: 767: SystemDriveConfiguration config; 768: 769: string winDir = GetWindowsDirectory(); 770: 771: // Scan all drives 772: for (int driveNumber = 0; driveNumber < 32; ++driveNumber) 773: { 774: bool windowsFound = false; 775: config.SystemLoaderPresent = false; 776: 777: PartitionList partitions = GetDrivePartitions (driveNumber); 778: foreach (const Partition &part, partitions) 779: { 1.1.1.5 root 780: if (!part.MountPoint.empty() 781: && (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0)) 782: { 1.1 root 783: config.SystemLoaderPresent = true; 1.1.1.5 root 784: } 1.1.1.8 ! root 785: else if (!part.VolumeNameId.empty() ! 786: && (_waccess ((part.VolumeNameId + L"\\bootmgr").c_str(), 0) == 0 || _waccess ((part.VolumeNameId + L"\\ntldr").c_str(), 0) == 0)) ! 787: { ! 788: config.SystemLoaderPresent = true; ! 789: } 1.1 root 790: 1.1.1.6 root 791: if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0) 1.1 root 792: { 793: config.SystemPartition = part; 794: windowsFound = true; 795: } 796: } 797: 798: if (windowsFound) 799: { 800: config.DriveNumber = driveNumber; 801: 802: stringstream ss; 803: ss << "PhysicalDrive" << driveNumber; 804: config.DevicePath = ss.str(); 805: 1.1.1.5 root 806: stringstream kernelPath; 807: kernelPath << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; 808: config.DeviceKernelPath = kernelPath.str(); 809: 1.1 root 810: config.DrivePartition = partitions.front(); 811: partitions.pop_front(); 812: config.Partitions = partitions; 813: 814: config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull; 815: config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart; 816: 817: foreach (const Partition &part, config.Partitions) 818: { 819: if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace) 820: config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart; 821: 822: config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart; 823: } 824: 825: DriveConfig = config; 1.1.1.5 root 826: DriveConfigValid = true; 1.1 root 827: return DriveConfig; 828: } 829: } 830: 831: throw ParameterIncorrect (SRC_POS); 832: } 833: 834: 835: bool BootEncryption::SystemPartitionCoversWholeDrive () 836: { 837: SystemDriveConfiguration config = GetSystemDriveConfiguration(); 838: 839: return config.Partitions.size() == 1 1.1.1.3 root 840: && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB; 1.1 root 841: } 842: 843: 1.1.1.3 root 844: uint32 BootEncryption::GetChecksum (byte *data, size_t size) 1.1 root 845: { 1.1.1.3 root 846: uint32 sum = 0; 847: 848: while (size-- > 0) 849: { 850: sum += *data++; 851: sum = _rotl (sum, 1); 852: } 853: 854: return sum; 855: } 856: 857: 1.1.1.6 root 858: void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation) 1.1.1.3 root 859: { 1.1.1.5 root 860: if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE) 1.1.1.3 root 861: throw ParameterIncorrect (SRC_POS); 862: 863: ZeroMemory (buffer, bufferSize); 864: 865: int ea = 0; 866: if (GetStatus().DriveMounted) 867: { 868: try 869: { 870: GetBootEncryptionAlgorithmNameRequest request; 871: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request)); 872: 873: if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0) 874: ea = AES; 875: else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0) 876: ea = SERPENT; 877: else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0) 878: ea = TWOFISH; 879: } 880: catch (...) 881: { 882: try 883: { 884: VOLUME_PROPERTIES_STRUCT properties; 885: GetVolumeProperties (&properties); 886: ea = properties.ea; 887: } 888: catch (...) { } 889: } 890: } 891: else 892: { 893: if (SelectedEncryptionAlgorithmId == 0) 894: throw ParameterIncorrect (SRC_POS); 895: 896: ea = SelectedEncryptionAlgorithmId; 897: } 898: 1.1.1.5 root 899: int bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR; 900: int bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER; 1.1.1.3 root 901: 902: switch (ea) 903: { 904: case AES: 1.1.1.5 root 905: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES; 906: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES; 1.1.1.3 root 907: break; 908: 909: case SERPENT: 1.1.1.5 root 910: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT; 911: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT; 1.1.1.3 root 912: break; 913: 914: case TWOFISH: 1.1.1.5 root 915: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH; 916: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH; 1.1.1.3 root 917: break; 918: } 919: 920: // Boot sector 1.1 root 921: DWORD size; 1.1.1.3 root 922: byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size); 923: if (!bootSecResourceImg || size != SECTOR_SIZE) 924: throw ParameterIncorrect (SRC_POS); 925: 926: memcpy (buffer, bootSecResourceImg, size); 1.1 root 927: 1.1.1.6 root 928: *(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM); 929: 1.1.1.8 ! root 930: if (IsOSAtLeast (WIN_VISTA)) 1.1.1.3 root 931: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER; 932: 1.1.1.6 root 933: // Checksum of the backup header of the outer volume for the hidden system 934: if (hiddenOSCreation) 935: { 936: Device device (GetSystemDriveConfiguration().DevicePath); 937: byte headerSector[SECTOR_SIZE]; 938: 939: device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE); 940: device.Read (headerSector, sizeof (headerSector)); 941: 1.1.1.8 ! root 942: *(uint32 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = GetCrc32 (headerSector, sizeof (headerSector)); 1.1.1.6 root 943: } 944: 1.1.1.3 root 945: // Decompressor 946: byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size); 947: if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE) 1.1 root 948: throw ParameterIncorrect (SRC_POS); 949: 1.1.1.3 root 950: memcpy (buffer + SECTOR_SIZE, decompressor, size); 1.1 root 951: 1.1.1.3 root 952: // Compressed boot loader 953: byte *bootLoader = MapResource ("BIN", bootLoaderId, &size); 954: if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE) 955: throw ParameterIncorrect (SRC_POS); 1.1 root 956: 1.1.1.3 root 957: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size); 1.1 root 958: 1.1.1.3 root 959: // Boot loader and decompressor checksum 960: *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast <uint16> (size); 961: *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE, 962: TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size); 963: 964: // Backup of decompressor and boot loader 965: if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE) 966: { 967: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE, 968: buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE); 969: 970: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE; 971: } 1.1.1.5 root 972: else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER) 1.1.1.3 root 973: { 974: throw ParameterIncorrect (SRC_POS); 975: } 976: } 977: 978: 1.1.1.8 ! root 979: void BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage, uint16 *bootLoaderVersion) 1.1.1.5 root 980: { 1.1.1.6 root 981: if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE) 1.1.1.5 root 982: throw ParameterIncorrect (SRC_POS); 983: 984: GetSystemDriveConfigurationRequest request; 985: _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); 986: 987: try 988: { 989: CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); 1.1.1.6 root 990: if (config) 991: *config = request.Configuration; 992: 993: if (userConfig) 994: *userConfig = request.UserConfiguration; 995: 996: if (customUserMessage) 997: { 998: request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0; 999: *customUserMessage = request.CustomUserMessage; 1000: } 1.1.1.8 ! root 1001: ! 1002: if (bootLoaderVersion) ! 1003: *bootLoaderVersion = request.BootLoaderVersion; 1.1.1.5 root 1004: } 1005: catch (...) 1006: { 1.1.1.6 root 1007: if (config) 1008: *config = 0; 1009: 1010: if (userConfig) 1011: *userConfig = 0; 1012: 1013: if (customUserMessage) 1014: customUserMessage->clear(); 1.1.1.8 ! root 1015: ! 1016: if (bootLoaderVersion) ! 1017: *bootLoaderVersion = 0; 1.1.1.5 root 1018: } 1019: } 1020: 1021: 1022: void BootEncryption::WriteBootSectorConfig (const byte newConfig[]) 1023: { 1024: Device device (GetSystemDriveConfiguration().DevicePath); 1025: byte mbr[SECTOR_SIZE]; 1026: 1027: device.SeekAt (0); 1028: device.Read (mbr, sizeof (mbr)); 1029: 1030: memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE); 1031: 1032: device.SeekAt (0); 1033: device.Write (mbr, sizeof (mbr)); 1034: 1035: byte mbrVerificationBuf[SECTOR_SIZE]; 1036: device.SeekAt (0); 1037: device.Read (mbrVerificationBuf, sizeof (mbr)); 1038: 1039: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) 1040: throw ErrorException ("ERROR_MBR_PROTECTED"); 1041: } 1042: 1043: 1.1.1.6 root 1044: void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage) 1045: { 1046: Device device (GetSystemDriveConfiguration().DevicePath); 1047: byte mbr[SECTOR_SIZE]; 1048: 1049: device.SeekAt (0); 1050: device.Read (mbr, sizeof (mbr)); 1051: 1.1.1.8 ! root 1052: if (!BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME) ! 1053: || BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)) > VERSION_NUM) ! 1054: { ! 1055: return; ! 1056: } ! 1057: 1.1.1.6 root 1058: mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig; 1059: 1060: memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); 1061: 1062: if (!customUserMessage.empty()) 1063: { 1064: if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH) 1065: throw ParameterIncorrect (SRC_POS); 1066: 1067: memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size()); 1068: } 1069: 1070: device.SeekAt (0); 1071: device.Write (mbr, sizeof (mbr)); 1072: 1073: byte mbrVerificationBuf[SECTOR_SIZE]; 1074: device.SeekAt (0); 1075: device.Read (mbrVerificationBuf, sizeof (mbr)); 1076: 1077: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) 1078: throw ErrorException ("ERROR_MBR_PROTECTED"); 1079: } 1080: 1081: 1.1.1.5 root 1082: unsigned int BootEncryption::GetHiddenOSCreationPhase () 1083: { 1084: byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; 1085: 1086: ReadBootSectorConfig (configFlags, sizeof(configFlags)); 1087: 1088: return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE); 1089: } 1090: 1091: 1092: void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase) 1093: { 1094: #if TC_BOOT_CFG_FLAG_AREA_SIZE != 1 1095: # error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase() 1096: #endif 1097: byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; 1098: 1099: ReadBootSectorConfig (configFlags, sizeof(configFlags)); 1100: 1101: configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; 1102: 1103: configFlags[0] |= newPhase; 1104: 1105: WriteBootSectorConfig (configFlags); 1106: } 1107: 1108: 1.1.1.6 root 1109: #ifndef SETUP 1110: 1111: void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm) 1112: { 1113: if (!IsHiddenOSRunning()) 1114: throw ParameterIncorrect (SRC_POS); 1115: 1116: WipeDecoySystemRequest request; 1117: ZeroMemory (&request, sizeof (request)); 1118: 1119: request.WipeAlgorithm = wipeAlgorithm; 1120: 1121: if (Randinit() != ERR_SUCCESS) 1122: throw ParameterIncorrect (SRC_POS); 1123: 1.1.1.8 ! root 1124: UserEnrichRandomPool (ParentWindow); ! 1125: 1.1.1.6 root 1126: if (!RandgetBytes (request.WipeKey, sizeof (request.WipeKey), TRUE)) 1127: throw ParameterIncorrect (SRC_POS); 1128: 1129: CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0); 1130: 1131: burn (&request, sizeof (request)); 1132: } 1133: 1134: 1135: void BootEncryption::AbortDecoyOSWipe () 1136: { 1137: CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE); 1138: } 1139: 1140: 1141: DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus () 1142: { 1143: DecoySystemWipeStatus status; 1144: CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status)); 1145: return status; 1146: } 1147: 1148: 1149: void BootEncryption::CheckDecoyOSWipeResult () 1150: { 1151: CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT); 1152: } 1153: 1154: 1155: void BootEncryption::WipeHiddenOSCreationConfig () 1156: { 1157: if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS) 1158: throw ParameterIncorrect (SRC_POS); 1159: 1160: Device device (GetSystemDriveConfiguration().DevicePath); 1161: byte mbr[SECTOR_SIZE]; 1162: 1163: device.SeekAt (0); 1164: device.Read (mbr, sizeof (mbr)); 1165: 1166: finally_do_arg (BootEncryption *, this, 1167: { 1168: try 1169: { 1170: finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); 1171: } catch (...) { } 1172: }); 1173: 1174: #if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE 1175: # error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE 1176: #endif 1177: 1178: byte randData[PRAND_DISK_WIPE_PASSES]; 1179: if (!RandgetBytes (randData, sizeof (randData), FALSE)) 1180: throw ParameterIncorrect (SRC_POS); 1181: 1182: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) 1183: { 1184: for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i) 1185: { 1186: mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass]; 1187: } 1188: 1189: mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; 1190: mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; 1191: 1192: if (wipePass == PRAND_DISK_WIPE_PASSES - 1) 1193: memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE); 1194: 1195: device.SeekAt (0); 1196: device.Write (mbr, sizeof (mbr)); 1197: } 1198: 1199: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++) 1200: { 1201: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); 1202: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING); 1203: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING); 1204: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED); 1205: } 1206: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); 1207: } 1208: 1209: #endif // !SETUP 1210: 1211: 1212: void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation) 1.1.1.3 root 1213: { 1.1.1.5 root 1214: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; 1.1.1.6 root 1215: CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation); 1.1.1.3 root 1216: 1217: // Write MBR 1218: Device device (GetSystemDriveConfiguration().DevicePath); 1219: byte mbr[SECTOR_SIZE]; 1.1 root 1220: 1221: device.SeekAt (0); 1.1.1.3 root 1222: device.Read (mbr, sizeof (mbr)); 1.1 root 1223: 1.1.1.8 ! root 1224: if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME)) 1.1.1.6 root 1225: { 1226: uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)); 1227: if (version != 0) 1228: { 1229: bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; 1230: memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); 1231: } 1232: } 1233: 1.1.1.3 root 1234: memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE); 1.1 root 1235: 1.1.1.3 root 1236: device.SeekAt (0); 1237: device.Write (mbr, sizeof (mbr)); 1.1 root 1238: 1.1.1.3 root 1239: byte mbrVerificationBuf[SECTOR_SIZE]; 1240: device.SeekAt (0); 1241: device.Read (mbrVerificationBuf, sizeof (mbr)); 1.1 root 1242: 1.1.1.3 root 1243: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) 1244: throw ErrorException ("ERROR_MBR_PROTECTED"); 1.1 root 1245: 1.1.1.3 root 1246: // Write boot loader 1.1 root 1247: device.SeekAt (SECTOR_SIZE); 1.1.1.3 root 1248: device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE); 1.1 root 1249: } 1250: 1251: 1252: string BootEncryption::GetSystemLoaderBackupPath () 1253: { 1254: char pathBuf[MAX_PATH]; 1255: 1256: throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf))); 1257: 1258: string path = string (pathBuf) + "\\" TC_APP_NAME; 1259: CreateDirectory (path.c_str(), NULL); 1260: 1261: return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME; 1262: } 1263: 1.1.1.3 root 1264: 1.1.1.5 root 1265: void BootEncryption::RenameDeprecatedSystemLoaderBackup () 1266: { 1267: char pathBuf[MAX_PATH]; 1268: 1269: if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf))) 1270: { 1271: string path = string (pathBuf) + "\\" TC_APP_NAME + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY; 1272: 1273: if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str())) 1274: throw_sys_if (rename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0); 1275: } 1276: } 1277: 1278: 1.1.1.2 root 1279: #ifndef SETUP 1.1 root 1280: void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath) 1281: { 1282: BootEncryptionStatus encStatus = GetStatus(); 1283: if (encStatus.SetupInProgress) 1284: throw ParameterIncorrect (SRC_POS); 1285: 1286: Buffer imageBuf (RescueIsoImageSize); 1287: 1288: byte *image = imageBuf.Ptr(); 1289: memset (image, 0, RescueIsoImageSize); 1290: 1291: // Primary volume descriptor 1.1.1.2 root 1292: strcpy ((char *)image + 0x8000, "\001CD001\001"); 1293: strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk "); 1294: *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048; 1295: *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048); 1296: image[0x7fff + 121] = 1; 1297: image[0x7fff + 124] = 1; 1298: image[0x7fff + 125] = 1; 1299: image[0x7fff + 128] = 1; 1300: image[0x7fff + 130] = 8; 1301: image[0x7fff + 131] = 8; 1302: 1303: image[0x7fff + 133] = 10; 1304: image[0x7fff + 140] = 10; 1305: image[0x7fff + 141] = 0x14; 1306: image[0x7fff + 157] = 0x22; 1307: image[0x7fff + 159] = 0x18; 1.1 root 1308: 1309: // Boot record volume descriptor 1310: strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION"); 1311: image[0x8800 + 0x47] = 0x19; 1312: 1.1.1.2 root 1313: // Volume descriptor set terminator 1314: strcpy ((char *)image + 0x9000, "\377CD001\001"); 1315: 1316: // Path table 1317: image[0xA000 + 0] = 1; 1318: image[0xA000 + 2] = 0x18; 1319: image[0xA000 + 6] = 1; 1320: 1321: // Root directory 1322: image[0xc000 + 0] = 0x22; 1323: image[0xc000 + 2] = 0x18; 1324: image[0xc000 + 9] = 0x18; 1325: image[0xc000 + 11] = 0x08; 1326: image[0xc000 + 16] = 0x08; 1327: image[0xc000 + 25] = 0x02; 1328: image[0xc000 + 28] = 0x01; 1329: image[0xc000 + 31] = 0x01; 1330: image[0xc000 + 32] = 0x01; 1331: image[0xc000 + 34] = 0x22; 1332: image[0xc000 + 36] = 0x18; 1333: image[0xc000 + 43] = 0x18; 1334: image[0xc000 + 45] = 0x08; 1335: image[0xc000 + 50] = 0x08; 1336: image[0xc000 + 59] = 0x02; 1337: image[0xc000 + 62] = 0x01; 1338: *(uint32 *) (image + 0xc000 + 65) = 0x010101; 1339: 1.1 root 1340: // Validation entry 1341: image[0xc800] = 1; 1.1.1.2 root 1342: int offset = 0xc800 + 0x1c; 1.1 root 1343: image[offset++] = 0xaa; 1344: image[offset++] = 0x55; 1345: image[offset++] = 0x55; 1346: image[offset] = 0xaa; 1347: 1348: // Initial entry 1349: offset = 0xc820; 1350: image[offset++] = 0x88; 1351: image[offset++] = 2; 1352: image[0xc820 + 6] = 1; 1353: image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR; 1354: 1355: // TrueCrypt Boot Loader 1.1.1.5 root 1356: CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true); 1.1 root 1357: 1358: // Volume header 1359: if (initialSetup) 1360: { 1361: if (!RescueVolumeHeaderValid) 1362: throw ParameterIncorrect (SRC_POS); 1363: 1.1.1.5 root 1364: memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); 1.1 root 1365: } 1366: else 1367: { 1368: Device bootDevice (GetSystemDriveConfiguration().DevicePath, true); 1369: bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); 1.1.1.5 root 1370: bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); 1.1 root 1371: } 1372: 1373: // Original system loader 1374: try 1375: { 1376: File sysBakFile (GetSystemLoaderBackupPath(), true); 1377: sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE); 1378: 1379: image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER; 1380: } 1381: catch (Exception &e) 1382: { 1383: e.Show (ParentWindow); 1384: Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK"); 1385: } 1386: 1.1.1.5 root 1387: // Boot loader backup 1388: CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false); 1389: 1.1 root 1390: RescueIsoImage = new byte[RescueIsoImageSize]; 1391: if (!RescueIsoImage) 1392: throw bad_alloc(); 1393: memcpy (RescueIsoImage, image, RescueIsoImageSize); 1394: 1395: if (!isoImagePath.empty()) 1396: { 1397: File isoFile (isoImagePath, false, true); 1398: isoFile.Write (image, RescueIsoImageSize); 1399: } 1400: } 1.1.1.2 root 1401: #endif 1.1 root 1402: 1403: bool BootEncryption::VerifyRescueDisk () 1404: { 1405: if (!RescueIsoImage) 1406: throw ParameterIncorrect (SRC_POS); 1407: 1408: for (char drive = 'Z'; drive >= 'D'; --drive) 1409: { 1410: try 1411: { 1412: string path = "X:"; 1413: path[0] = drive; 1414: 1415: Device driveDevice (path, true); 1416: size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048; 1417: Buffer buffer ((verifiedSectorCount + 1) * 2048); 1418: 1419: DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size()); 1420: if (bytesRead != buffer.Size()) 1421: continue; 1422: 1423: if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0) 1424: return true; 1425: } 1426: catch (...) { } 1427: } 1428: 1429: return false; 1430: } 1431: 1432: 1433: #ifndef SETUP 1434: 1435: void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5) 1436: { 1437: PCRYPTO_INFO cryptoInfo = NULL; 1.1.1.5 root 1438: 1.1.1.8 ! root 1439: if (!IsRandomNumberGeneratorStarted()) ! 1440: throw ParameterIncorrect (SRC_POS); ! 1441: 1.1.1.6 root 1442: throw_sys_if (CreateVolumeHeaderInMemory (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, &cryptoInfo, 1.1.1.5 root 1443: volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, FALSE) != 0); 1.1 root 1444: 1445: finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); }); 1446: 1447: // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize) 1448: memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader)); 1.1.1.6 root 1449: ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo); 1.1 root 1450: 1451: DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); 1452: 1453: if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545) 1454: throw ParameterIncorrect (SRC_POS); 1455: 1456: byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; 1457: mputInt64 (fieldPos, volumeSize); 1.1.1.5 root 1458: 1459: // CRC of the header fields 1460: uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); 1461: fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC; 1462: mputLong (fieldPos, crc); 1463: 1.1 root 1464: EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); 1465: 1466: VolumeHeaderValid = true; 1467: RescueVolumeHeaderValid = true; 1468: } 1469: 1470: 1471: void BootEncryption::InstallVolumeHeader () 1472: { 1473: if (!VolumeHeaderValid) 1474: throw ParameterIncorrect (SRC_POS); 1475: 1476: Device device (GetSystemDriveConfiguration().DevicePath); 1477: 1478: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); 1479: device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader)); 1480: } 1481: 1482: 1483: // For synchronous operations use AbortSetupWait() 1484: void BootEncryption::AbortSetup () 1485: { 1486: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); 1487: } 1488: 1489: 1490: // For asynchronous operations use AbortSetup() 1491: void BootEncryption::AbortSetupWait () 1492: { 1493: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); 1494: 1495: BootEncryptionStatus encStatus = GetStatus(); 1496: 1497: while (encStatus.SetupInProgress) 1498: { 1499: Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL); 1500: encStatus = GetStatus(); 1501: } 1502: } 1503: 1504: 1505: void BootEncryption::BackupSystemLoader () 1506: { 1507: Device device (GetSystemDriveConfiguration().DevicePath, true); 1508: 1509: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; 1510: 1511: device.SeekAt (0); 1512: device.Read (bootLoaderBuf, sizeof (bootLoaderBuf)); 1513: 1514: // Prevent TrueCrypt loader from being backed up 1515: for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i) 1516: { 1517: if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) 1518: { 1519: if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO) 1520: throw UserAbort (SRC_POS); 1521: return; 1522: } 1523: } 1524: 1525: File backupFile (GetSystemLoaderBackupPath(), false, true); 1526: backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); 1527: } 1528: 1529: 1530: void BootEncryption::RestoreSystemLoader () 1531: { 1532: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; 1533: 1534: File backupFile (GetSystemLoaderBackupPath(), true); 1535: 1536: if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf)) 1537: throw ParameterIncorrect (SRC_POS); 1538: 1539: Device device (GetSystemDriveConfiguration().DevicePath); 1.1.1.4 root 1540: 1541: // Preserve current partition table 1542: byte mbr[SECTOR_SIZE]; 1543: device.SeekAt (0); 1544: device.Read (mbr, sizeof (mbr)); 1545: memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE); 1546: 1.1 root 1547: device.SeekAt (0); 1548: device.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); 1549: } 1550: 1.1.1.3 root 1551: #endif // SETUP 1.1 root 1552: 1.1.1.5 root 1553: void BootEncryption::RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid) 1.1 root 1554: { 1.1.1.5 root 1555: HKEY classRegKey = SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE); 1.1 root 1556: throw_sys_if (classRegKey == INVALID_HANDLE_VALUE); 1557: finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); }); 1558: 1.1.1.5 root 1559: if (registerFilter) 1.1 root 1560: { 1.1.1.5 root 1561: // Register class filter below all other filters in the stack 1562: 1.1 root 1563: size_t strSize = strlen ("truecrypt") + 1; 1564: byte regKeyBuf[65536]; 1565: DWORD size = sizeof (regKeyBuf) - strSize; 1566: 1567: // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly 1568: strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf)); 1569: 1570: if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS) 1571: size = 1; 1572: 1573: throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS); 1574: } 1575: else 1576: { 1.1.1.5 root 1577: // Unregister a class filter 1.1.1.6 root 1578: string infFileName = GetTempPath() + "\\truecrypt_device_filter.inf"; 1.1 root 1579: 1580: File infFile (infFileName, false, true); 1.1.1.5 root 1581: finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); }); 1.1 root 1582: 1.1.1.5 root 1583: string infTxt = "[truecrypt]\r\n" 1584: "DelReg=truecrypt_reg\r\n\r\n" 1585: "[truecrypt_reg]\r\n" 1586: "HKR,,\"UpperFilters\",0x00018002,\"truecrypt\"\r\n"; 1.1 root 1587: 1588: infFile.Write ((byte *) infTxt.c_str(), infTxt.size()); 1589: infFile.Close(); 1590: 1591: HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); 1592: throw_sys_if (hInf == INVALID_HANDLE_VALUE); 1593: finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); }); 1594: 1595: throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL)); 1596: } 1597: } 1.1.1.5 root 1598: 1599: void BootEncryption::RegisterFilterDriver (bool registerDriver, bool volumeClass) 1600: { 1601: if (!IsAdmin() && IsUacSupported()) 1602: { 1603: Elevator::RegisterFilterDriver (registerDriver, volumeClass); 1604: return; 1605: } 1606: 1607: if (volumeClass) 1608: { 1609: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_VOLUME); 1610: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_FLOPPYDISK); 1611: } 1612: else 1613: { 1614: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_DISKDRIVE); 1615: } 1616: } 1.1 root 1617: 1.1.1.3 root 1618: #ifndef SETUP 1.1 root 1619: 1620: void BootEncryption::CheckRequirements () 1621: { 1622: if (nCurrentOS == WIN_2000) 1623: throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS"); 1.1.1.8 ! root 1624: ! 1625: if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1) ! 1626: throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0"); 1.1 root 1627: 1628: if (IsNonInstallMode()) 1629: throw ErrorException ("FEATURE_REQUIRES_INSTALLATION"); 1630: 1631: SystemDriveConfiguration config = GetSystemDriveConfiguration (); 1632: 1633: if (config.SystemPartition.IsGPT) 1634: throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED"); 1635: 1.1.1.5 root 1636: if (SystemDriveIsDynamic()) 1637: throw ErrorException ("SYSENC_UNSUPPORTED_FOR_DYNAMIC_DISK"); 1638: 1.1 root 1639: if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE) 1640: throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER"); 1641: 1642: DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); 1643: 1644: if (geometry.BytesPerSector != SECTOR_SIZE) 1645: throw ErrorException ("LARGE_SECTOR_UNSUPPORTED"); 1646: 1647: if (!config.SystemLoaderPresent) 1648: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); 1.1.1.5 root 1649: 1650: if (!config.SystemPartition.IsGPT) 1651: { 1652: // Determine whether there is an Active partition on the system drive 1653: bool activePartitionFound = false; 1654: foreach (const Partition &partition, config.Partitions) 1655: { 1656: if (partition.Info.BootIndicator) 1657: { 1658: activePartitionFound = true; 1659: break; 1660: } 1661: } 1662: 1663: if (!activePartitionFound) 1664: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); 1665: } 1666: } 1667: 1668: 1669: void BootEncryption::CheckRequirementsHiddenOS () 1670: { 1671: // It is assumed that CheckRequirements() had been called (so we don't check e.g. whether it's GPT). 1672: 1673: // The user may have modified/added/deleted partitions since the partition table was last scanned. 1674: InvalidateCachedSysDriveProperties (); 1675: 1676: GetPartitionForHiddenOS (); 1.1 root 1677: } 1678: 1679: 1.1.1.6 root 1680: void BootEncryption::InitialSecurityChecksForHiddenOS () 1681: { 1682: char windowsDrive = toupper (GetWindowsDirectory()[0]); 1683: 1684: // Paging files 1.1.1.8 ! root 1685: bool pagingFilesOk = !IsPagingFileActive (TRUE); 1.1.1.6 root 1686: 1687: char pagingFileRegData[65536]; 1688: DWORD pagingFileRegDataSize = sizeof (pagingFileRegData); 1689: 1690: if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFileRegData, &pagingFileRegDataSize) 1691: && pagingFileRegDataSize > 4) 1692: { 1693: for (size_t i = 1; i < pagingFileRegDataSize - 2; ++i) 1694: { 1695: if (memcmp (pagingFileRegData + i, ":\\", 2) == 0 && toupper (pagingFileRegData[i - 1]) != windowsDrive) 1696: { 1.1.1.8 ! root 1697: pagingFilesOk = false; ! 1698: break; 1.1.1.6 root 1699: } 1700: } 1701: } 1702: 1.1.1.8 ! root 1703: if (!pagingFilesOk) ! 1704: { ! 1705: if (AskWarnYesNoString ((wchar_t *) (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) ! 1706: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION") ! 1707: + L"\n\n\n" ! 1708: + GetString ("RESTRICT_PAGING_FILES_TO_SYS_PARTITION") ! 1709: ).c_str()) == IDYES) ! 1710: { ! 1711: RestrictPagingFilesToSystemPartition(); ! 1712: RestartComputer(); ! 1713: AbortProcessSilent(); ! 1714: } ! 1715: ! 1716: throw ErrorException (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) ! 1717: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); ! 1718: } ! 1719: 1.1.1.6 root 1720: // User profile 1721: char *configPath = GetConfigPath ("dummy"); 1722: if (configPath && toupper (configPath[0]) != windowsDrive) 1723: { 1724: throw ErrorException (wstring (GetString ("USER_PROFILE_NOT_ON_SYS_PARTITION")) 1725: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); 1726: } 1727: 1728: // Temporary files 1729: if (toupper (GetTempPath()[0]) != windowsDrive) 1730: { 1731: throw ErrorException (wstring (GetString ("TEMP_NOT_ON_SYS_PARTITION")) 1732: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); 1733: } 1734: } 1735: 1736: 1.1 root 1737: void BootEncryption::Deinstall () 1738: { 1739: BootEncryptionStatus encStatus = GetStatus(); 1740: 1741: if (encStatus.DriveEncrypted || encStatus.DriveMounted) 1742: throw ParameterIncorrect (SRC_POS); 1743: 1744: SystemDriveConfiguration config = GetSystemDriveConfiguration (); 1745: 1746: if (encStatus.VolumeHeaderPresent) 1747: { 1748: // Verify CRC of header salt 1749: Device device (config.DevicePath, true); 1.1.1.5 root 1750: byte header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; 1.1 root 1751: 1752: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); 1753: device.Read (header, sizeof (header)); 1754: 1755: if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE)) 1756: throw ParameterIncorrect (SRC_POS); 1757: } 1758: 1.1.1.5 root 1759: RegisterFilterDriver (false, false); 1760: RegisterFilterDriver (false, true); 1.1 root 1761: SetDriverServiceStartType (SERVICE_SYSTEM_START); 1762: 1.1.1.5 root 1763: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); // In case RestoreSystemLoader() fails 1764: 1.1 root 1765: try 1766: { 1767: RestoreSystemLoader (); 1768: } 1769: catch (Exception &e) 1770: { 1771: e.Show (ParentWindow); 1772: throw ErrorException ("SYS_LOADER_RESTORE_FAILED"); 1773: } 1774: } 1775: 1776: 1777: int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5) 1778: { 1.1.1.5 root 1779: BootEncryptionStatus encStatus = GetStatus(); 1780: 1781: if (encStatus.SetupInProgress) 1.1 root 1782: throw ParameterIncorrect (SRC_POS); 1783: 1784: SystemDriveConfiguration config = GetSystemDriveConfiguration (); 1785: 1.1.1.5 root 1786: char header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; 1.1 root 1787: Device device (config.DevicePath); 1788: 1789: // Only one algorithm is currently supported 1790: if (pkcs5 != 0) 1791: throw ParameterIncorrect (SRC_POS); 1792: 1.1.1.5 root 1793: int64 headerOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; 1794: int64 backupHeaderOffset = -1; 1795: 1796: if (encStatus.HiddenSystem) 1797: { 1798: headerOffset = encStatus.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; 1799: 1800: // Find hidden system partition 1801: foreach (const Partition &partition, config.Partitions) 1802: { 1803: if (partition.Info.StartingOffset.QuadPart == encStatus.HiddenSystemPartitionStart) 1804: { 1805: backupHeaderOffset = partition.Info.StartingOffset.QuadPart + partition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_SIZE; 1806: break; 1807: } 1808: } 1809: 1810: if (backupHeaderOffset == -1) 1811: throw ParameterIncorrect (SRC_POS); 1812: } 1813: 1814: device.SeekAt (headerOffset); 1.1 root 1815: device.Read ((byte *) header, sizeof (header)); 1816: 1817: PCRYPTO_INFO cryptoInfo = NULL; 1818: 1.1.1.6 root 1819: int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, &cryptoInfo, NULL); 1.1 root 1820: finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); }); 1821: 1822: if (status != 0) 1823: { 1824: handleError (ParentWindow, status); 1825: return status; 1826: } 1827: 1828: // Change the PKCS-5 PRF if requested by user 1829: if (pkcs5 != 0) 1.1.1.8 ! root 1830: { 1.1 root 1831: cryptoInfo->pkcs5 = pkcs5; 1.1.1.8 ! root 1832: RandSetHashFunction (pkcs5); ! 1833: } 1.1 root 1834: 1835: throw_sys_if (Randinit () != 0); 1.1.1.8 ! root 1836: finally_do ({ RandStop (FALSE); }); ! 1837: ! 1838: NormalCursor(); ! 1839: UserEnrichRandomPool (ParentWindow); ! 1840: WaitCursor(); 1.1 root 1841: 1842: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using 1843: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy 1844: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 1845: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might 1846: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the 1847: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman 1848: recommends. During each pass we will write a valid working header. Each pass will use the same master 1849: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only 1850: item that will be different for each pass will be the salt. This is sufficient to cause each "version" 1851: of the header to differ substantially and in a random manner from the versions written during the 1852: other passes. */ 1853: 1854: bool headerUpdated = false; 1855: int result = ERR_SUCCESS; 1856: 1857: try 1858: { 1.1.1.5 root 1859: BOOL backupHeader = FALSE; 1860: while (TRUE) 1.1 root 1861: { 1.1.1.5 root 1862: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) 1.1 root 1863: { 1.1.1.5 root 1864: PCRYPTO_INFO tmpCryptoInfo = NULL; 1865: 1.1.1.6 root 1866: status = CreateVolumeHeaderInMemory (!encStatus.HiddenSystem, 1.1.1.5 root 1867: header, 1868: cryptoInfo->ea, 1869: cryptoInfo->mode, 1870: newPassword, 1871: cryptoInfo->pkcs5, 1872: (char *) cryptoInfo->master_keydata, 1873: &tmpCryptoInfo, 1874: cryptoInfo->VolumeSize.Value, 1875: cryptoInfo->hiddenVolumeSize, 1876: cryptoInfo->EncryptedAreaStart.Value, 1877: cryptoInfo->EncryptedAreaLength.Value, 1878: cryptoInfo->RequiredProgramVersion, 1879: cryptoInfo->HeaderFlags | TC_HEADER_FLAG_ENCRYPTED_SYSTEM, 1880: wipePass < PRAND_DISK_WIPE_PASSES - 1); 1881: 1882: if (tmpCryptoInfo) 1883: crypto_close (tmpCryptoInfo); 1884: 1885: if (status != 0) 1886: { 1887: handleError (ParentWindow, status); 1888: return status; 1889: } 1890: 1891: device.SeekAt (headerOffset); 1892: device.Write ((byte *) header, sizeof (header)); 1893: headerUpdated = true; 1.1 root 1894: } 1895: 1.1.1.5 root 1896: if (!encStatus.HiddenSystem || backupHeader) 1897: break; 1898: 1899: backupHeader = TRUE; 1900: headerOffset = backupHeaderOffset; 1.1 root 1901: } 1902: } 1903: catch (Exception &e) 1904: { 1905: e.Show (ParentWindow); 1906: result = ERR_OS_ERROR; 1907: } 1908: 1909: if (headerUpdated) 1910: { 1911: ReopenBootVolumeHeaderRequest reopenRequest; 1912: reopenRequest.VolumePassword = *newPassword; 1913: finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); }); 1914: 1915: CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest)); 1916: } 1917: 1918: return result; 1919: } 1920: 1921: 1922: void BootEncryption::CheckEncryptionSetupResult () 1923: { 1.1.1.7 root 1924: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT); 1.1 root 1925: } 1926: 1927: 1.1.1.6 root 1928: void BootEncryption::Install (bool hiddenSystem) 1.1 root 1929: { 1930: BootEncryptionStatus encStatus = GetStatus(); 1931: if (encStatus.DriveMounted) 1932: throw ParameterIncorrect (SRC_POS); 1933: 1934: try 1935: { 1.1.1.6 root 1936: InstallBootLoader (false, hiddenSystem); 1937: 1938: if (!hiddenSystem) 1939: InstallVolumeHeader (); 1940: 1941: RegisterBootDriver (hiddenSystem); 1.1 root 1942: } 1943: catch (Exception &) 1944: { 1945: try 1946: { 1947: RestoreSystemLoader (); 1948: } 1949: catch (Exception &e) 1950: { 1951: e.Show (ParentWindow); 1952: } 1953: 1954: throw; 1955: } 1956: } 1957: 1958: 1.1.1.6 root 1959: void BootEncryption::PrepareHiddenOSCreation (int ea, int mode, int pkcs5) 1960: { 1961: BootEncryptionStatus encStatus = GetStatus(); 1962: if (encStatus.DriveMounted) 1963: throw ParameterIncorrect (SRC_POS); 1964: 1965: CheckRequirements(); 1966: BackupSystemLoader(); 1967: 1968: SelectedEncryptionAlgorithmId = ea; 1969: } 1970: 1971: 1.1 root 1972: void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath) 1973: { 1974: BootEncryptionStatus encStatus = GetStatus(); 1975: if (encStatus.DriveMounted) 1976: throw ParameterIncorrect (SRC_POS); 1977: 1978: CheckRequirements (); 1979: 1980: SystemDriveConfiguration config = GetSystemDriveConfiguration(); 1.1.1.7 root 1981: 1982: // Some chipset drivers may prevent access to the last sector of the drive 1983: if (!systemPartitionOnly) 1984: { 1985: DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); 1986: Buffer sector (geometry.BytesPerSector); 1987: 1988: Device device (config.DevicePath); 1989: 1990: try 1991: { 1992: device.SeekAt (config.DrivePartition.Info.PartitionLength.QuadPart - geometry.BytesPerSector); 1993: device.Read (sector.Ptr(), sector.Size()); 1994: } 1995: catch (SystemException &e) 1996: { 1997: if (e.ErrorCode != ERROR_CRC) 1998: { 1999: e.Show (ParentWindow); 2000: Error ("WHOLE_DRIVE_ENCRYPTION_PREVENTED_BY_DRIVERS"); 2001: throw UserAbort (SRC_POS); 2002: } 2003: } 2004: } 2005: 1.1 root 2006: BackupSystemLoader (); 2007: 2008: uint64 volumeSize; 2009: uint64 encryptedAreaStart; 2010: 2011: if (systemPartitionOnly) 2012: { 2013: volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart; 2014: encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart; 2015: } 2016: else 2017: { 2018: volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE; 2019: encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE; 2020: } 2021: 1.1.1.3 root 2022: SelectedEncryptionAlgorithmId = ea; 1.1 root 2023: CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5); 2024: 2025: if (!rescueIsoImagePath.empty()) 2026: CreateRescueIsoImage (true, rescueIsoImagePath); 2027: } 2028: 1.1.1.6 root 2029: bool BootEncryption::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) 1.1.1.5 root 2030: { 2031: if (!IsAdmin() && IsUacSupported()) 1.1.1.6 root 2032: return Elevator::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; 1.1.1.5 root 2033: 1.1.1.6 root 2034: return ::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; 1.1.1.5 root 2035: } 2036: 1.1.1.8 ! root 2037: void BootEncryption::RestrictPagingFilesToSystemPartition () ! 2038: { ! 2039: char pagingFiles[128]; ! 2040: strncpy (pagingFiles, "X:\\pagefile.sys 0 0", sizeof (pagingFiles)); ! 2041: pagingFiles[0] = GetWindowsDirectory()[0]; ! 2042: ! 2043: throw_sys_if (!WriteLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFiles, strlen (pagingFiles) + 2)); ! 2044: } 1.1.1.5 root 2045: 2046: void BootEncryption::WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) 2047: { 2048: if (!IsAdmin() && IsUacSupported()) 2049: { 2050: Elevator::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); 2051: return; 2052: } 2053: 2054: throw_sys_if (!WriteLocalMachineRegistryDword (keyPath, valueName, value)); 2055: } 2056: 2057: 1.1.1.8 ! root 2058: void BootEncryption::StartDecryption (BOOL discardUnreadableEncryptedSectors) 1.1 root 2059: { 2060: BootEncryptionStatus encStatus = GetStatus(); 2061: 2062: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) 2063: throw ParameterIncorrect (SRC_POS); 2064: 2065: BootEncryptionSetupRequest request; 2066: ZeroMemory (&request, sizeof (request)); 2067: 2068: request.SetupMode = SetupDecryption; 1.1.1.8 ! root 2069: request.DiscardUnreadableEncryptedSectors = discardUnreadableEncryptedSectors; 1.1 root 2070: 2071: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); 2072: } 2073: 2074: 1.1.1.6 root 2075: void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors) 1.1 root 2076: { 2077: BootEncryptionStatus encStatus = GetStatus(); 2078: 2079: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) 2080: throw ParameterIncorrect (SRC_POS); 2081: 2082: BootEncryptionSetupRequest request; 2083: ZeroMemory (&request, sizeof (request)); 2084: 2085: request.SetupMode = SetupEncryption; 2086: request.WipeAlgorithm = wipeAlgorithm; 1.1.1.6 root 2087: request.ZeroUnreadableSectors = zeroUnreadableSectors; 1.1 root 2088: 2089: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); 2090: } 2091: 1.1.1.2 root 2092: #endif // !SETUP 1.1 root 2093: 1.1.1.6 root 2094: 2095: void BootEncryption::WriteBootDriveSector (uint64 offset, byte *data) 2096: { 2097: WriteBootDriveSectorRequest request; 2098: request.Offset.QuadPart = offset; 2099: memcpy (request.Data, data, sizeof (request.Data)); 2100: 2101: CallDriver (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR, &request, sizeof (request), NULL, 0); 2102: } 2103: 2104: 2105: void BootEncryption::RegisterBootDriver (bool hiddenSystem) 1.1.1.3 root 2106: { 2107: SetDriverServiceStartType (SERVICE_BOOT_START); 2108: 2109: try 2110: { 1.1.1.5 root 2111: RegisterFilterDriver (false, false); 2112: RegisterFilterDriver (false, true); 1.1.1.3 root 2113: } 2114: catch (...) { } 2115: 1.1.1.5 root 2116: RegisterFilterDriver (true, false); 1.1.1.6 root 2117: 2118: if (hiddenSystem) 2119: RegisterFilterDriver (true, true); 1.1.1.3 root 2120: } 2121: 2122: 1.1 root 2123: bool BootEncryption::RestartComputer (void) 2124: { 1.1.1.5 root 2125: return (::RestartComputer() != FALSE); 1.1 root 2126: } 2127: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.