|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
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"
24: #include "Random.h"
25: #include "Registry.h"
26: #include "Volumes.h"
27:
28: #ifdef VOLFORMAT
29: #include "Format/FormatCom.h"
30: #elif defined (TCMOUNT)
31: #include "Mount/MainCom.h"
32: #endif
33:
34: namespace TrueCrypt
35: {
36: #if !defined (SETUP)
37:
38: class Elevator
39: {
40: public:
41: static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
42: {
43: Elevate();
44:
45: CComBSTR inputBstr;
46: if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK)
47: throw ParameterIncorrect (SRC_POS);
48:
49: CComBSTR outputBstr;
50: if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK)
51: throw ParameterIncorrect (SRC_POS);
52:
53: DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr);
54: if (result != ERROR_SUCCESS)
55: {
56: SetLastError (result);
57: throw SystemException();
58: }
59: }
60:
61: static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone)
62: {
63: Elevate();
64:
65: CComBSTR bufferBstr;
66: if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK)
67: throw ParameterIncorrect (SRC_POS);
68: DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone);
69:
70: if (result != ERROR_SUCCESS)
71: {
72: SetLastError (result);
73: throw SystemException();
74: }
75:
76: if (!write)
77: memcpy (buffer, (BYTE *) bufferBstr.m_str, size);
78: }
79:
80: static void RegisterFilterDriver (bool registerDriver)
81: {
82: Elevate();
83:
84: DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE);
85: if (result != ERROR_SUCCESS)
86: {
87: SetLastError (result);
88: throw SystemException();
89: }
90: }
91:
92: static void Release ()
93: {
94: if (ElevatedComInstance)
95: {
96: ElevatedComInstance->Release();
97: ElevatedComInstance = nullptr;
98: CoUninitialize ();
99: }
100: }
101:
102: static void SetDriverServiceStartType (DWORD startType)
103: {
104: Elevate();
105:
106: DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType);
107: if (result != ERROR_SUCCESS)
108: {
109: SetLastError (result);
110: throw SystemException();
111: }
112: }
113:
114: protected:
115: static void Elevate ()
116: {
117: if (IsAdmin())
118: {
119: SetLastError (ERROR_ACCESS_DENIED);
120: throw SystemException();
121: }
122:
123: if (!ElevatedComInstance)
124: {
125: CoInitialize (NULL);
126: ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg);
127: }
128: }
129:
130: #if defined (TCMOUNT)
131: static ITrueCryptMainCom *ElevatedComInstance;
132: #elif defined (VOLFORMAT)
133: static ITrueCryptFormatCom *ElevatedComInstance;
134: #endif
135: };
136:
137: #if defined (TCMOUNT)
138: ITrueCryptMainCom *Elevator::ElevatedComInstance;
139: #elif defined (VOLFORMAT)
140: ITrueCryptFormatCom *Elevator::ElevatedComInstance;
141: #endif
142:
143: #else // SETUP
144:
145: class Elevator
146: {
147: public:
148: static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); }
149: static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); }
150: static void RegisterFilterDriver (bool registerDriver) { throw ParameterIncorrect (SRC_POS); }
151: static void Release () { }
152: static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); }
153: };
154:
155: #endif // SETUP
156:
157:
158: File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false)
159: {
160: Handle = CreateFile (path.c_str(),
161: readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
162: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
163: FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
164:
165: try
166: {
167: throw_sys_if (Handle == INVALID_HANDLE_VALUE);
168: }
169: catch (SystemException &)
170: {
171: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
172: Elevated = true;
173: else
174: throw;
175: }
176:
177: FileOpen = true;
178: FilePointerPosition = 0;
179: IsDevice = false;
180: Path = path;
181: }
182:
183: void File::Close ()
184: {
185: if (FileOpen)
186: {
187: if (!Elevated)
188: CloseHandle (Handle);
189:
190: FileOpen = false;
191: }
192: }
193:
194: DWORD File::Read (byte *buffer, DWORD size)
195: {
196: DWORD bytesRead;
197:
198: if (Elevated)
199: {
200: DWORD bytesRead;
201:
202: Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead);
203: FilePointerPosition += bytesRead;
204: return bytesRead;
205: }
206:
207: throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL));
208: return bytesRead;
209: }
210:
211: void File::SeekAt (int64 position)
212: {
213: if (Elevated)
214: {
215: FilePointerPosition = position;
216: }
217: else
218: {
219: LARGE_INTEGER pos;
220: pos.QuadPart = position;
221: throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN));
222: }
223: }
224:
225: void File::Write (byte *buffer, DWORD size)
226: {
227: DWORD bytesWritten;
228:
229: if (Elevated)
230: {
231: Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten);
232: FilePointerPosition += bytesWritten;
233: throw_sys_if (bytesWritten != size);
234: }
235: else
236: {
237: throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size);
238: }
239: }
240:
241: void Show (HWND parent, const string &str)
242: {
243: MessageBox (parent, str.c_str(), NULL, 0);
244: }
245:
246:
247: Device::Device (string path, bool readOnly)
248: {
249: FileOpen = false;
250: Elevated = false;
251:
252: Handle = CreateFile ((string ("\\\\.\\") + path).c_str(),
253: readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
254: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
255: FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
256:
257: try
258: {
259: throw_sys_if (Handle == INVALID_HANDLE_VALUE);
260: }
261: catch (SystemException &)
262: {
263: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
264: Elevated = true;
265: else
266: throw;
267: }
268:
269: FileOpen = true;
270: FilePointerPosition = 0;
271: IsDevice = true;
272: Path = path;
273: }
274:
275:
276: BootEncryption::~BootEncryption ()
277: {
278: if (RescueIsoImage)
279: delete RescueIsoImage;
280:
281: Elevator::Release();
282: }
283:
284:
285: void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
286: {
287: try
288: {
289: DWORD bytesReturned;
290: throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL));
291: }
292: catch (SystemException &)
293: {
294: if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
295: Elevator::CallDriver (ioctl, input, inputSize, output, outputSize);
296: else
297: throw;
298: }
299: }
300:
301:
302: DWORD BootEncryption::GetDriverServiceStartType ()
303: {
304: DWORD startType;
305: throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType));
306: return startType;
307: }
308:
309:
310: void BootEncryption::SetDriverServiceStartType (DWORD startType)
311: {
312: if (!IsAdmin() && IsUacSupported())
313: {
314: Elevator::SetDriverServiceStartType (startType);
315: return;
316: }
317:
318: BOOL startOnBoot = (startType == SERVICE_BOOT_START);
319:
320: SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
321: throw_sys_if (!serviceManager);
322:
323: finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); });
324:
325: SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG);
326: throw_sys_if (!service);
327:
328: finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); });
329:
330: throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
331: startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, NULL,
332: startOnBoot ? "Filter" : NULL,
333: NULL, NULL, NULL, NULL, NULL));
334:
335: // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER
336: throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType));
337: }
338:
339:
340: void BootEncryption::ProbeRealSystemDriveSize ()
341: {
342: if (RealSystemDriveSizeValid)
343: return;
344:
345: GetSystemDriveConfiguration();
346:
347: ProbeRealDriveSizeRequest request;
348: _snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str());
349:
350: CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request));
351: DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize;
352:
353: RealSystemDriveSizeValid = TRUE;
1.1.1.3 ! root 354:
! 355: if (request.TimeOut)
! 356: throw TimeOut (SRC_POS);
1.1 root 357: }
358:
359:
360: PartitionList BootEncryption::GetDrivePartitions (int driveNumber)
361: {
362: PartitionList partList;
363:
364: for (int partNumber = 0; partNumber < 64; ++partNumber)
365: {
366: stringstream partPath;
367: partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber;
368:
369: DISK_PARTITION_INFO_STRUCT diskPartInfo;
370: _snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str());
371:
372: try
373: {
374: CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo));
375: }
376: catch (...)
377: {
378: continue;
379: }
380:
381: Partition part;
382: part.DevicePath = partPath.str();
383: part.Number = partNumber;
384: part.Info = diskPartInfo.partInfo;
385: part.IsGPT = diskPartInfo.IsGPT;
386:
387: // Mount point
388: wstringstream ws;
389: ws << partPath.str().c_str();
390: int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str());
391:
392: if (driveNumber >= 0)
393: {
394: part.MountPoint += (char) (driveNumber + 'A');
395: part.MountPoint += ":";
396: }
397: partList.push_back (part);
398: }
399:
400: return partList;
401: }
402:
403:
404: DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber)
405: {
406: stringstream devName;
407: devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
408:
409: DISK_GEOMETRY geometry;
410: throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry));
411: return geometry;
412: }
413:
414:
415: string BootEncryption::GetWindowsDirectory ()
416: {
417: char buf[MAX_PATH];
418: if (GetSystemDirectory (buf, sizeof (buf)) > 0)
419: return string (buf);
420:
421: return string();
422: }
423:
424:
425: uint16 BootEncryption::GetInstalledBootLoaderVersion ()
426: {
427: uint16 version;
428: CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version));
429: return version;
430: }
431:
432:
1.1.1.3 ! root 433: // Note that this does not require admin rights (it just requires the driver to be running)
! 434: bool BootEncryption::IsBootLoaderOnDrive (char *devicePath)
! 435: {
! 436: try
! 437: {
! 438: OPEN_TEST_STRUCT openTestStruct;
! 439: DWORD dwResult;
! 440:
! 441: strcpy ((char *) &openTestStruct.wszFileName[0], devicePath);
! 442: ToUNICODE ((char *) &openTestStruct.wszFileName[0]);
! 443:
! 444: openTestStruct.bDetectTCBootLoader = TRUE;
! 445:
! 446: return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
! 447: &openTestStruct, sizeof (OPEN_TEST_STRUCT),
! 448: NULL, 0,
! 449: &dwResult, NULL) == TRUE);
! 450: }
! 451: catch (...)
! 452: {
! 453: return false;
! 454: }
! 455: }
! 456:
! 457:
1.1 root 458: BootEncryptionStatus BootEncryption::GetStatus ()
459: {
460: /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
461:
462: BootEncryptionStatus status;
463: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status));
464: return status;
465: }
466:
467:
468: void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties)
469: {
470: if (properties == NULL)
471: throw ParameterIncorrect (SRC_POS);
472:
473: CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties));
474: }
475:
476:
1.1.1.2 root 477: bool BootEncryption::SystemDriveContainsPartitionType (byte type)
478: {
479: Device device (GetSystemDriveConfiguration().DevicePath, true);
480:
481: byte mbrBuf[SECTOR_SIZE];
482: device.SeekAt (0);
483: device.Read (mbrBuf, sizeof (mbrBuf));
484:
485: MBR *mbr = reinterpret_cast <MBR *> (mbrBuf);
486: if (mbr->Signature != 0xaa55)
487: throw ParameterIncorrect (SRC_POS);
488:
489: for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i)
490: {
491: if (mbr->Partitions[i].Type == type)
492: return true;
493: }
494:
495: return false;
496: }
497:
498:
499: bool BootEncryption::SystemDriveContainsExtendedPartition ()
500: {
501: return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED);
502: }
503:
504:
505: bool BootEncryption::SystemDriveIsDynamic ()
506: {
507: return SystemDriveContainsPartitionType (PARTITION_LDM);
508: }
509:
510:
1.1 root 511: SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration ()
512: {
513: if (DriveConfigValid)
514: return DriveConfig;
515:
516: SystemDriveConfiguration config;
517:
518: string winDir = GetWindowsDirectory();
519:
520: // Scan all drives
521: for (int driveNumber = 0; driveNumber < 32; ++driveNumber)
522: {
523: bool windowsFound = false;
524: config.SystemLoaderPresent = false;
525:
526: PartitionList partitions = GetDrivePartitions (driveNumber);
527: foreach (const Partition &part, partitions)
528: {
529: if (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0)
530: config.SystemLoaderPresent = true;
531:
532: if (!windowsFound && !part.MountPoint.empty() && winDir.find (part.MountPoint) == 0)
533: {
534: config.SystemPartition = part;
535: windowsFound = true;
536: }
537: }
538:
539: if (windowsFound)
540: {
541: config.DriveNumber = driveNumber;
542:
543: stringstream ss;
544: ss << "PhysicalDrive" << driveNumber;
545: config.DevicePath = ss.str();
546:
547: config.DrivePartition = partitions.front();
548: partitions.pop_front();
549: config.Partitions = partitions;
550:
551: config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull;
552: config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart;
553:
554: foreach (const Partition &part, config.Partitions)
555: {
556: if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace)
557: config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart;
558:
559: config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart;
560: }
561:
562: DriveConfig = config;
563: DriveConfigValid = TRUE;
564: return DriveConfig;
565: }
566: }
567:
568: throw ParameterIncorrect (SRC_POS);
569: }
570:
571:
572: bool BootEncryption::SystemPartitionCoversWholeDrive ()
573: {
574: SystemDriveConfiguration config = GetSystemDriveConfiguration();
575:
576: return config.Partitions.size() == 1
1.1.1.3 ! root 577: && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB;
1.1 root 578: }
579:
580:
1.1.1.3 ! root 581: uint32 BootEncryption::GetChecksum (byte *data, size_t size)
1.1 root 582: {
1.1.1.3 ! root 583: uint32 sum = 0;
! 584:
! 585: while (size-- > 0)
! 586: {
! 587: sum += *data++;
! 588: sum = _rotl (sum, 1);
! 589: }
! 590:
! 591: return sum;
! 592: }
! 593:
! 594:
! 595: void BootEncryption::GetBootLoader (byte *buffer, size_t bufferSize, bool rescueDisk)
! 596: {
! 597: if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - HEADER_SIZE)
! 598: throw ParameterIncorrect (SRC_POS);
! 599:
! 600: ZeroMemory (buffer, bufferSize);
! 601:
! 602: int ea = 0;
! 603: if (GetStatus().DriveMounted)
! 604: {
! 605: try
! 606: {
! 607: GetBootEncryptionAlgorithmNameRequest request;
! 608: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request));
! 609:
! 610: if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0)
! 611: ea = AES;
! 612: else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
! 613: ea = SERPENT;
! 614: else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
! 615: ea = TWOFISH;
! 616: }
! 617: catch (...)
! 618: {
! 619: try
! 620: {
! 621: VOLUME_PROPERTIES_STRUCT properties;
! 622: GetVolumeProperties (&properties);
! 623: ea = properties.ea;
! 624: }
! 625: catch (...) { }
! 626: }
! 627: }
! 628: else
! 629: {
! 630: if (SelectedEncryptionAlgorithmId == 0)
! 631: throw ParameterIncorrect (SRC_POS);
! 632:
! 633: ea = SelectedEncryptionAlgorithmId;
! 634: }
! 635:
! 636: int bootSectorId = IDR_BOOT_SECTOR;
! 637: int bootLoaderId = IDR_BOOT_LOADER;
! 638:
! 639: switch (ea)
! 640: {
! 641: case AES:
! 642: bootSectorId = IDR_BOOT_SECTOR_AES;
! 643: bootLoaderId = IDR_BOOT_LOADER_AES;
! 644: break;
! 645:
! 646: case SERPENT:
! 647: bootSectorId = IDR_BOOT_SECTOR_SERPENT;
! 648: bootLoaderId = IDR_BOOT_LOADER_SERPENT;
! 649: break;
! 650:
! 651: case TWOFISH:
! 652: bootSectorId = IDR_BOOT_SECTOR_TWOFISH;
! 653: bootLoaderId = IDR_BOOT_LOADER_TWOFISH;
! 654: break;
! 655: }
! 656:
! 657: // Boot sector
1.1 root 658: DWORD size;
1.1.1.3 ! root 659: byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size);
! 660: if (!bootSecResourceImg || size != SECTOR_SIZE)
! 661: throw ParameterIncorrect (SRC_POS);
! 662:
! 663: memcpy (buffer, bootSecResourceImg, size);
1.1 root 664:
1.1.1.3 ! root 665: if (rescueDisk)
! 666: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK;
! 667:
! 668: if (nCurrentOS == WIN_VISTA_OR_LATER)
! 669: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
! 670:
! 671: // Decompressor
! 672: byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size);
! 673: if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE)
1.1 root 674: throw ParameterIncorrect (SRC_POS);
675:
1.1.1.3 ! root 676: memcpy (buffer + SECTOR_SIZE, decompressor, size);
1.1 root 677:
1.1.1.3 ! root 678: // Compressed boot loader
! 679: byte *bootLoader = MapResource ("BIN", bootLoaderId, &size);
! 680: if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE)
! 681: throw ParameterIncorrect (SRC_POS);
1.1 root 682:
1.1.1.3 ! root 683: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size);
1.1 root 684:
1.1.1.3 ! root 685: // Boot loader and decompressor checksum
! 686: *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast <uint16> (size);
! 687: *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE,
! 688: TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size);
! 689:
! 690: // Backup of decompressor and boot loader
! 691: if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE)
! 692: {
! 693: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE,
! 694: buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE);
! 695:
! 696: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE;
! 697: }
! 698: else if (bootLoaderId != IDR_BOOT_LOADER)
! 699: {
! 700: throw ParameterIncorrect (SRC_POS);
! 701: }
! 702: }
! 703:
! 704:
! 705: void BootEncryption::InstallBootLoader ()
! 706: {
! 707: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - HEADER_SIZE];
! 708: GetBootLoader (bootLoaderBuf, sizeof (bootLoaderBuf), false);
! 709:
! 710: // Write MBR
! 711: Device device (GetSystemDriveConfiguration().DevicePath);
! 712: byte mbr[SECTOR_SIZE];
1.1 root 713:
714: device.SeekAt (0);
1.1.1.3 ! root 715: device.Read (mbr, sizeof (mbr));
1.1 root 716:
1.1.1.3 ! root 717: memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
1.1 root 718:
1.1.1.3 ! root 719: device.SeekAt (0);
! 720: device.Write (mbr, sizeof (mbr));
1.1 root 721:
1.1.1.3 ! root 722: byte mbrVerificationBuf[SECTOR_SIZE];
! 723: device.SeekAt (0);
! 724: device.Read (mbrVerificationBuf, sizeof (mbr));
1.1 root 725:
1.1.1.3 ! root 726: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
! 727: throw ErrorException ("ERROR_MBR_PROTECTED");
1.1 root 728:
1.1.1.3 ! root 729: // Write boot loader
1.1 root 730: device.SeekAt (SECTOR_SIZE);
1.1.1.3 ! root 731: device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE);
1.1 root 732: }
733:
734:
735: string BootEncryption::GetSystemLoaderBackupPath ()
736: {
737: char pathBuf[MAX_PATH];
738:
739: throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf)));
740:
741: string path = string (pathBuf) + "\\" TC_APP_NAME;
742: CreateDirectory (path.c_str(), NULL);
743:
744: return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME;
745: }
746:
1.1.1.3 ! root 747:
1.1.1.2 root 748: #ifndef SETUP
1.1 root 749: void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath)
750: {
751: BootEncryptionStatus encStatus = GetStatus();
752: if (encStatus.SetupInProgress)
753: throw ParameterIncorrect (SRC_POS);
754:
755: Buffer imageBuf (RescueIsoImageSize);
756:
757: byte *image = imageBuf.Ptr();
758: memset (image, 0, RescueIsoImageSize);
759:
760: // Primary volume descriptor
1.1.1.2 root 761: strcpy ((char *)image + 0x8000, "\001CD001\001");
762: strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk ");
763: *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048;
764: *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048);
765: image[0x7fff + 121] = 1;
766: image[0x7fff + 124] = 1;
767: image[0x7fff + 125] = 1;
768: image[0x7fff + 128] = 1;
769: image[0x7fff + 130] = 8;
770: image[0x7fff + 131] = 8;
771:
772: image[0x7fff + 133] = 10;
773: image[0x7fff + 140] = 10;
774: image[0x7fff + 141] = 0x14;
775: image[0x7fff + 157] = 0x22;
776: image[0x7fff + 159] = 0x18;
1.1 root 777:
778: // Boot record volume descriptor
779: strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION");
780: image[0x8800 + 0x47] = 0x19;
781:
1.1.1.2 root 782: // Volume descriptor set terminator
783: strcpy ((char *)image + 0x9000, "\377CD001\001");
784:
785: // Path table
786: image[0xA000 + 0] = 1;
787: image[0xA000 + 2] = 0x18;
788: image[0xA000 + 6] = 1;
789:
790: // Root directory
791: image[0xc000 + 0] = 0x22;
792: image[0xc000 + 2] = 0x18;
793: image[0xc000 + 9] = 0x18;
794: image[0xc000 + 11] = 0x08;
795: image[0xc000 + 16] = 0x08;
796: image[0xc000 + 25] = 0x02;
797: image[0xc000 + 28] = 0x01;
798: image[0xc000 + 31] = 0x01;
799: image[0xc000 + 32] = 0x01;
800: image[0xc000 + 34] = 0x22;
801: image[0xc000 + 36] = 0x18;
802: image[0xc000 + 43] = 0x18;
803: image[0xc000 + 45] = 0x08;
804: image[0xc000 + 50] = 0x08;
805: image[0xc000 + 59] = 0x02;
806: image[0xc000 + 62] = 0x01;
807: *(uint32 *) (image + 0xc000 + 65) = 0x010101;
808:
1.1 root 809: // Validation entry
810: image[0xc800] = 1;
1.1.1.2 root 811: int offset = 0xc800 + 0x1c;
1.1 root 812: image[offset++] = 0xaa;
813: image[offset++] = 0x55;
814: image[offset++] = 0x55;
815: image[offset] = 0xaa;
816:
817: // Initial entry
818: offset = 0xc820;
819: image[offset++] = 0x88;
820: image[offset++] = 2;
821: image[0xc820 + 6] = 1;
822: image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR;
823:
824: // TrueCrypt Boot Loader
1.1.1.3 ! root 825: GetBootLoader (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true);
1.1 root 826:
827: // Volume header
828: if (initialSetup)
829: {
830: if (!RescueVolumeHeaderValid)
831: throw ParameterIncorrect (SRC_POS);
832:
833: memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, HEADER_SIZE);
834: }
835: else
836: {
837: Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
838: bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
839: bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, HEADER_SIZE);
840: }
841:
842: // Original system loader
843: try
844: {
845: File sysBakFile (GetSystemLoaderBackupPath(), true);
846: sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE);
847:
848: image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER;
849: }
850: catch (Exception &e)
851: {
852: e.Show (ParentWindow);
853: Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK");
854: }
855:
856: RescueIsoImage = new byte[RescueIsoImageSize];
857: if (!RescueIsoImage)
858: throw bad_alloc();
859: memcpy (RescueIsoImage, image, RescueIsoImageSize);
860:
861: if (!isoImagePath.empty())
862: {
863: File isoFile (isoImagePath, false, true);
864: isoFile.Write (image, RescueIsoImageSize);
865: }
866: }
1.1.1.2 root 867: #endif
1.1 root 868:
869: bool BootEncryption::VerifyRescueDisk ()
870: {
871: if (!RescueIsoImage)
872: throw ParameterIncorrect (SRC_POS);
873:
874: for (char drive = 'Z'; drive >= 'D'; --drive)
875: {
876: try
877: {
878: string path = "X:";
879: path[0] = drive;
880:
881: Device driveDevice (path, true);
882: size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
883: Buffer buffer ((verifiedSectorCount + 1) * 2048);
884:
885: DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size());
886: if (bytesRead != buffer.Size())
887: continue;
888:
889: if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
890: return true;
891: }
892: catch (...) { }
893: }
894:
895: return false;
896: }
897:
898:
899: #ifndef SETUP
900:
901: void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5)
902: {
903: PCRYPTO_INFO cryptoInfo = NULL;
904:
905: throw_sys_if (Randinit () != 0);
906: throw_sys_if (VolumeWriteHeader (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, 0, &cryptoInfo,
907: volumeSize, 0, encryptedAreaStart, 0, FALSE) != 0);
908:
909: finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); });
910:
911: // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
912: memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
913: VolumeReadHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo);
914:
915: DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
916:
917: if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
918: throw ParameterIncorrect (SRC_POS);
919:
920: byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
921: mputInt64 (fieldPos, volumeSize);
922:
923: EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
924:
925: VolumeHeaderValid = true;
926: RescueVolumeHeaderValid = true;
927: }
928:
929:
930: void BootEncryption::InstallVolumeHeader ()
931: {
932: if (!VolumeHeaderValid)
933: throw ParameterIncorrect (SRC_POS);
934:
935: Device device (GetSystemDriveConfiguration().DevicePath);
936:
937: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
938: device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader));
939: }
940:
941:
942: // For synchronous operations use AbortSetupWait()
943: void BootEncryption::AbortSetup ()
944: {
945: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
946: }
947:
948:
949: // For asynchronous operations use AbortSetup()
950: void BootEncryption::AbortSetupWait ()
951: {
952: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
953:
954: BootEncryptionStatus encStatus = GetStatus();
955:
956: while (encStatus.SetupInProgress)
957: {
958: Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL);
959: encStatus = GetStatus();
960: }
961: }
962:
963:
964: void BootEncryption::BackupSystemLoader ()
965: {
966: Device device (GetSystemDriveConfiguration().DevicePath, true);
967:
968: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
969:
970: device.SeekAt (0);
971: device.Read (bootLoaderBuf, sizeof (bootLoaderBuf));
972:
973: // Prevent TrueCrypt loader from being backed up
974: for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i)
975: {
976: if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
977: {
978: if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO)
979: throw UserAbort (SRC_POS);
980: return;
981: }
982: }
983:
984: File backupFile (GetSystemLoaderBackupPath(), false, true);
985: backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
986: }
987:
988:
989: void BootEncryption::RestoreSystemLoader ()
990: {
991: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
992:
993: File backupFile (GetSystemLoaderBackupPath(), true);
994:
995: if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf))
996: throw ParameterIncorrect (SRC_POS);
997:
998: Device device (GetSystemDriveConfiguration().DevicePath);
999: device.SeekAt (0);
1000: device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
1001: }
1002:
1.1.1.3 ! root 1003: #endif // SETUP
1.1 root 1004:
1005: void BootEncryption::RegisterFilterDriver (bool registerDriver)
1006: {
1007: if (!IsAdmin() && IsUacSupported())
1008: {
1009: Elevator::RegisterFilterDriver (registerDriver);
1010: return;
1011: }
1012:
1013: HKEY classRegKey = SetupDiOpenClassRegKey (&GUID_DEVCLASS_DISKDRIVE, KEY_READ | KEY_WRITE);
1014: throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
1015: finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
1016:
1.1.1.2 root 1017: if (registerDriver && nCurrentOS == WIN_VISTA_OR_LATER)
1.1 root 1018: {
1.1.1.2 root 1019: // Attaching to the device stack after PartMgr on Vista causes all write IRPs sent to the lower device object to fail
1020: // with STATUS_ACCESS_DENIED. Therefore, our filter is placed in front of others already registered.
1.1 root 1021: size_t strSize = strlen ("truecrypt") + 1;
1022: byte regKeyBuf[65536];
1023: DWORD size = sizeof (regKeyBuf) - strSize;
1024:
1025: // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly
1026: strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf));
1027:
1028: if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS)
1029: size = 1;
1030:
1031: throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS);
1032: }
1033: else
1034: {
1035: char tempPath[MAX_PATH];
1036: GetTempPath (sizeof (tempPath), tempPath);
1037: string infFileName = string (tempPath) + "\\truecrypt_filter.inf";
1038:
1039: finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
1040: File infFile (infFileName, false, true);
1041:
1.1.1.2 root 1042: string infTxt = "[truecrypt]\r\n" + string (registerDriver ? "Add" : "Del") + "Reg=truecrypt_reg\r\n\r\n"
1043: "[truecrypt_reg]\r\nHKR,,\"UpperFilters\",0x0001" + string (registerDriver ? "0008" : "8002") + ",\"truecrypt\"\r\n";
1.1 root 1044:
1045: infFile.Write ((byte *) infTxt.c_str(), infTxt.size());
1046: infFile.Close();
1047:
1048: HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
1049: throw_sys_if (hInf == INVALID_HANDLE_VALUE);
1050: finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
1051:
1052: throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL));
1053: }
1054: }
1055:
1.1.1.3 ! root 1056: #ifndef SETUP
1.1 root 1057:
1058: void BootEncryption::CheckRequirements ()
1059: {
1060: if (nCurrentOS == WIN_2000)
1061: throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS");
1062:
1063: if (IsNonInstallMode())
1064: throw ErrorException ("FEATURE_REQUIRES_INSTALLATION");
1065:
1066: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1067:
1068: if (config.SystemPartition.IsGPT)
1069: throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED");
1070:
1071: if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE)
1072: throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER");
1073:
1074: DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber);
1075:
1076: if (geometry.BytesPerSector != SECTOR_SIZE)
1077: throw ErrorException ("LARGE_SECTOR_UNSUPPORTED");
1078:
1079: if (!config.SystemLoaderPresent)
1080: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
1081: }
1082:
1083:
1084: void BootEncryption::Deinstall ()
1085: {
1086: BootEncryptionStatus encStatus = GetStatus();
1087:
1088: if (encStatus.DriveEncrypted || encStatus.DriveMounted)
1089: throw ParameterIncorrect (SRC_POS);
1090:
1091: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1092:
1093: if (encStatus.VolumeHeaderPresent)
1094: {
1095: // Verify CRC of header salt
1096: Device device (config.DevicePath, true);
1097: byte header[SECTOR_SIZE];
1098:
1099: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1100: device.Read (header, sizeof (header));
1101:
1102: if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE))
1103: throw ParameterIncorrect (SRC_POS);
1104: }
1105:
1106: RegisterFilterDriver (false);
1107: SetDriverServiceStartType (SERVICE_SYSTEM_START);
1108:
1109: try
1110: {
1111: RestoreSystemLoader ();
1112: }
1113: catch (Exception &e)
1114: {
1115: e.Show (ParentWindow);
1116: throw ErrorException ("SYS_LOADER_RESTORE_FAILED");
1117: }
1118: }
1119:
1120:
1121: int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5)
1122: {
1123: if (GetStatus().SetupInProgress)
1124: throw ParameterIncorrect (SRC_POS);
1125:
1126: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1127:
1128: char header[HEADER_SIZE];
1129: Device device (config.DevicePath);
1130:
1131: // Only one algorithm is currently supported
1132: if (pkcs5 != 0)
1133: throw ParameterIncorrect (SRC_POS);
1134:
1135: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1136: device.Read ((byte *) header, sizeof (header));
1137:
1138: PCRYPTO_INFO cryptoInfo = NULL;
1139:
1140: int status = VolumeReadHeader (TRUE, header, oldPassword, &cryptoInfo, NULL);
1141: finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
1142:
1143: if (status != 0)
1144: {
1145: handleError (ParentWindow, status);
1146: return status;
1147: }
1148:
1149: // Change the PKCS-5 PRF if requested by user
1150: if (pkcs5 != 0)
1151: cryptoInfo->pkcs5 = pkcs5;
1152:
1153: throw_sys_if (Randinit () != 0);
1154:
1155: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
1156: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
1157: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
1158: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
1159: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
1160: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
1161: recommends. During each pass we will write a valid working header. Each pass will use the same master
1162: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
1163: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
1164: of the header to differ substantially and in a random manner from the versions written during the
1165: other passes. */
1166:
1167: bool headerUpdated = false;
1168: int result = ERR_SUCCESS;
1169:
1170: try
1171: {
1172: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
1173: {
1174: PCRYPTO_INFO tmpCryptoInfo = NULL;
1175:
1176: status = VolumeWriteHeader (TRUE,
1177: header,
1178: cryptoInfo->ea,
1179: cryptoInfo->mode,
1180: newPassword,
1181: cryptoInfo->pkcs5,
1182: (char *) cryptoInfo->master_keydata,
1183: cryptoInfo->volume_creation_time,
1184: &tmpCryptoInfo,
1185: cryptoInfo->VolumeSize.Value,
1186: cryptoInfo->hiddenVolumeSize,
1187: cryptoInfo->EncryptedAreaStart.Value,
1188: cryptoInfo->EncryptedAreaLength.Value,
1189: wipePass < PRAND_DISK_WIPE_PASSES - 1);
1190:
1191: if (tmpCryptoInfo)
1192: crypto_close (tmpCryptoInfo);
1193:
1194: if (status != 0)
1195: {
1196: handleError (ParentWindow, status);
1197: return status;
1198: }
1199:
1200: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1201: device.Write ((byte *) header, sizeof (header));
1202: headerUpdated = true;
1203: }
1204: }
1205: catch (Exception &e)
1206: {
1207: e.Show (ParentWindow);
1208: result = ERR_OS_ERROR;
1209: }
1210:
1211: if (headerUpdated)
1212: {
1213: ReopenBootVolumeHeaderRequest reopenRequest;
1214: reopenRequest.VolumePassword = *newPassword;
1215: finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); });
1216:
1217: CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
1218: }
1219:
1220: return result;
1221: }
1222:
1223:
1224: void BootEncryption::CheckEncryptionSetupResult ()
1225: {
1226: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
1227: }
1228:
1229:
1230: void BootEncryption::Install ()
1231: {
1232: BootEncryptionStatus encStatus = GetStatus();
1233: if (encStatus.DriveMounted)
1234: throw ParameterIncorrect (SRC_POS);
1235:
1236: try
1237: {
1238: InstallBootLoader ();
1239: InstallVolumeHeader ();
1.1.1.3 ! root 1240: RegisterBootDriver ();
1.1 root 1241:
1.1.1.3 ! root 1242: // Prevent system log errors caused by rejecting crash dumps
! 1243: WriteLocalMachineRegistryDword ("System\\CurrentControlSet\\Control\\CrashControl", "CrashDumpEnabled", 0);
1.1 root 1244: }
1245: catch (Exception &)
1246: {
1247: try
1248: {
1249: RestoreSystemLoader ();
1250: }
1251: catch (Exception &e)
1252: {
1253: e.Show (ParentWindow);
1254: }
1255:
1256: throw;
1257: }
1258: }
1259:
1260:
1261: void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath)
1262: {
1263: if (!systemPartitionOnly && !RealSystemDriveSizeValid)
1264: ProbeRealSystemDriveSize();
1265:
1266: BootEncryptionStatus encStatus = GetStatus();
1267: if (encStatus.DriveMounted)
1268: throw ParameterIncorrect (SRC_POS);
1269:
1270: CheckRequirements ();
1271:
1272: SystemDriveConfiguration config = GetSystemDriveConfiguration();
1273: BackupSystemLoader ();
1274:
1275: uint64 volumeSize;
1276: uint64 encryptedAreaStart;
1277:
1278: if (systemPartitionOnly)
1279: {
1280: volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart;
1281: encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart;
1282: }
1283: else
1284: {
1285: volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE;
1286: encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE;
1287: }
1288:
1.1.1.3 ! root 1289: SelectedEncryptionAlgorithmId = ea;
1.1 root 1290: CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5);
1291:
1292: if (!rescueIsoImagePath.empty())
1293: CreateRescueIsoImage (true, rescueIsoImagePath);
1294: }
1295:
1296:
1297: void BootEncryption::StartDecryption ()
1298: {
1299: BootEncryptionStatus encStatus = GetStatus();
1300:
1301: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1302: throw ParameterIncorrect (SRC_POS);
1303:
1304: BootEncryptionSetupRequest request;
1305: ZeroMemory (&request, sizeof (request));
1306:
1307: request.SetupMode = SetupDecryption;
1308:
1309: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
1310: }
1311:
1312:
1313: void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm)
1314: {
1315: BootEncryptionStatus encStatus = GetStatus();
1316:
1317: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1318: throw ParameterIncorrect (SRC_POS);
1319:
1320: BootEncryptionSetupRequest request;
1321: ZeroMemory (&request, sizeof (request));
1322:
1323: request.SetupMode = SetupEncryption;
1324: request.WipeAlgorithm = wipeAlgorithm;
1325:
1326: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
1327: }
1328:
1.1.1.2 root 1329: #endif // !SETUP
1.1 root 1330:
1.1.1.3 ! root 1331: void BootEncryption::RegisterBootDriver (void)
! 1332: {
! 1333: SetDriverServiceStartType (SERVICE_BOOT_START);
! 1334:
! 1335: try
! 1336: {
! 1337: RegisterFilterDriver (false);
! 1338: }
! 1339: catch (...) { }
! 1340:
! 1341: RegisterFilterDriver (true);
! 1342: }
! 1343:
! 1344:
1.1 root 1345: bool BootEncryption::RestartComputer (void)
1346: {
1347: TOKEN_PRIVILEGES tokenPrivil;
1348: HANDLE hTkn;
1349:
1350: if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn))
1351: {
1352: return false;
1353: }
1354:
1355: LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid);
1356: tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1357: tokenPrivil.PrivilegeCount = 1;
1358:
1359: AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0);
1360: if (GetLastError() != ERROR_SUCCESS)
1361: return false;
1362:
1363: if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE,
1364: SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
1365: return false;
1366:
1367: return true;
1368: }
1369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.