|
|
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);
1.1.1.4 ! root 999:
! 1000: // Preserve current partition table
! 1001: byte mbr[SECTOR_SIZE];
! 1002: device.SeekAt (0);
! 1003: device.Read (mbr, sizeof (mbr));
! 1004: memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE);
! 1005:
1.1 root 1006: device.SeekAt (0);
1007: device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
1008: }
1009:
1.1.1.3 root 1010: #endif // SETUP
1.1 root 1011:
1012: void BootEncryption::RegisterFilterDriver (bool registerDriver)
1013: {
1014: if (!IsAdmin() && IsUacSupported())
1015: {
1016: Elevator::RegisterFilterDriver (registerDriver);
1017: return;
1018: }
1019:
1020: HKEY classRegKey = SetupDiOpenClassRegKey (&GUID_DEVCLASS_DISKDRIVE, KEY_READ | KEY_WRITE);
1021: throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
1022: finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
1023:
1.1.1.2 root 1024: if (registerDriver && nCurrentOS == WIN_VISTA_OR_LATER)
1.1 root 1025: {
1.1.1.2 root 1026: // Attaching to the device stack after PartMgr on Vista causes all write IRPs sent to the lower device object to fail
1027: // with STATUS_ACCESS_DENIED. Therefore, our filter is placed in front of others already registered.
1.1 root 1028: size_t strSize = strlen ("truecrypt") + 1;
1029: byte regKeyBuf[65536];
1030: DWORD size = sizeof (regKeyBuf) - strSize;
1031:
1032: // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly
1033: strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf));
1034:
1035: if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS)
1036: size = 1;
1037:
1038: throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS);
1039: }
1040: else
1041: {
1042: char tempPath[MAX_PATH];
1043: GetTempPath (sizeof (tempPath), tempPath);
1044: string infFileName = string (tempPath) + "\\truecrypt_filter.inf";
1045:
1046: finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
1047: File infFile (infFileName, false, true);
1048:
1.1.1.2 root 1049: string infTxt = "[truecrypt]\r\n" + string (registerDriver ? "Add" : "Del") + "Reg=truecrypt_reg\r\n\r\n"
1050: "[truecrypt_reg]\r\nHKR,,\"UpperFilters\",0x0001" + string (registerDriver ? "0008" : "8002") + ",\"truecrypt\"\r\n";
1.1 root 1051:
1052: infFile.Write ((byte *) infTxt.c_str(), infTxt.size());
1053: infFile.Close();
1054:
1055: HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
1056: throw_sys_if (hInf == INVALID_HANDLE_VALUE);
1057: finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
1058:
1059: throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL));
1060: }
1061: }
1062:
1.1.1.3 root 1063: #ifndef SETUP
1.1 root 1064:
1065: void BootEncryption::CheckRequirements ()
1066: {
1067: if (nCurrentOS == WIN_2000)
1068: throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS");
1069:
1070: if (IsNonInstallMode())
1071: throw ErrorException ("FEATURE_REQUIRES_INSTALLATION");
1072:
1073: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1074:
1075: if (config.SystemPartition.IsGPT)
1076: throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED");
1077:
1078: if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE)
1079: throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER");
1080:
1081: DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber);
1082:
1083: if (geometry.BytesPerSector != SECTOR_SIZE)
1084: throw ErrorException ("LARGE_SECTOR_UNSUPPORTED");
1085:
1086: if (!config.SystemLoaderPresent)
1087: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
1088: }
1089:
1090:
1091: void BootEncryption::Deinstall ()
1092: {
1093: BootEncryptionStatus encStatus = GetStatus();
1094:
1095: if (encStatus.DriveEncrypted || encStatus.DriveMounted)
1096: throw ParameterIncorrect (SRC_POS);
1097:
1098: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1099:
1100: if (encStatus.VolumeHeaderPresent)
1101: {
1102: // Verify CRC of header salt
1103: Device device (config.DevicePath, true);
1104: byte header[SECTOR_SIZE];
1105:
1106: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1107: device.Read (header, sizeof (header));
1108:
1109: if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE))
1110: throw ParameterIncorrect (SRC_POS);
1111: }
1112:
1113: RegisterFilterDriver (false);
1114: SetDriverServiceStartType (SERVICE_SYSTEM_START);
1115:
1116: try
1117: {
1118: RestoreSystemLoader ();
1119: }
1120: catch (Exception &e)
1121: {
1122: e.Show (ParentWindow);
1123: throw ErrorException ("SYS_LOADER_RESTORE_FAILED");
1124: }
1125: }
1126:
1127:
1128: int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5)
1129: {
1130: if (GetStatus().SetupInProgress)
1131: throw ParameterIncorrect (SRC_POS);
1132:
1133: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1134:
1135: char header[HEADER_SIZE];
1136: Device device (config.DevicePath);
1137:
1138: // Only one algorithm is currently supported
1139: if (pkcs5 != 0)
1140: throw ParameterIncorrect (SRC_POS);
1141:
1142: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1143: device.Read ((byte *) header, sizeof (header));
1144:
1145: PCRYPTO_INFO cryptoInfo = NULL;
1146:
1147: int status = VolumeReadHeader (TRUE, header, oldPassword, &cryptoInfo, NULL);
1148: finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
1149:
1150: if (status != 0)
1151: {
1152: handleError (ParentWindow, status);
1153: return status;
1154: }
1155:
1156: // Change the PKCS-5 PRF if requested by user
1157: if (pkcs5 != 0)
1158: cryptoInfo->pkcs5 = pkcs5;
1159:
1160: throw_sys_if (Randinit () != 0);
1161:
1162: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
1163: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
1164: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
1165: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
1166: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
1167: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
1168: recommends. During each pass we will write a valid working header. Each pass will use the same master
1169: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
1170: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
1171: of the header to differ substantially and in a random manner from the versions written during the
1172: other passes. */
1173:
1174: bool headerUpdated = false;
1175: int result = ERR_SUCCESS;
1176:
1177: try
1178: {
1179: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
1180: {
1181: PCRYPTO_INFO tmpCryptoInfo = NULL;
1182:
1183: status = VolumeWriteHeader (TRUE,
1184: header,
1185: cryptoInfo->ea,
1186: cryptoInfo->mode,
1187: newPassword,
1188: cryptoInfo->pkcs5,
1189: (char *) cryptoInfo->master_keydata,
1190: cryptoInfo->volume_creation_time,
1191: &tmpCryptoInfo,
1192: cryptoInfo->VolumeSize.Value,
1193: cryptoInfo->hiddenVolumeSize,
1194: cryptoInfo->EncryptedAreaStart.Value,
1195: cryptoInfo->EncryptedAreaLength.Value,
1196: wipePass < PRAND_DISK_WIPE_PASSES - 1);
1197:
1198: if (tmpCryptoInfo)
1199: crypto_close (tmpCryptoInfo);
1200:
1201: if (status != 0)
1202: {
1203: handleError (ParentWindow, status);
1204: return status;
1205: }
1206:
1207: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1208: device.Write ((byte *) header, sizeof (header));
1209: headerUpdated = true;
1210: }
1211: }
1212: catch (Exception &e)
1213: {
1214: e.Show (ParentWindow);
1215: result = ERR_OS_ERROR;
1216: }
1217:
1218: if (headerUpdated)
1219: {
1220: ReopenBootVolumeHeaderRequest reopenRequest;
1221: reopenRequest.VolumePassword = *newPassword;
1222: finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); });
1223:
1224: CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
1225: }
1226:
1227: return result;
1228: }
1229:
1230:
1231: void BootEncryption::CheckEncryptionSetupResult ()
1232: {
1233: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
1234: }
1235:
1236:
1237: void BootEncryption::Install ()
1238: {
1239: BootEncryptionStatus encStatus = GetStatus();
1240: if (encStatus.DriveMounted)
1241: throw ParameterIncorrect (SRC_POS);
1242:
1243: try
1244: {
1245: InstallBootLoader ();
1246: InstallVolumeHeader ();
1.1.1.3 root 1247: RegisterBootDriver ();
1.1 root 1248:
1.1.1.3 root 1249: // Prevent system log errors caused by rejecting crash dumps
1250: WriteLocalMachineRegistryDword ("System\\CurrentControlSet\\Control\\CrashControl", "CrashDumpEnabled", 0);
1.1 root 1251: }
1252: catch (Exception &)
1253: {
1254: try
1255: {
1256: RestoreSystemLoader ();
1257: }
1258: catch (Exception &e)
1259: {
1260: e.Show (ParentWindow);
1261: }
1262:
1263: throw;
1264: }
1265: }
1266:
1267:
1268: void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath)
1269: {
1270: BootEncryptionStatus encStatus = GetStatus();
1271: if (encStatus.DriveMounted)
1272: throw ParameterIncorrect (SRC_POS);
1273:
1274: CheckRequirements ();
1275:
1276: SystemDriveConfiguration config = GetSystemDriveConfiguration();
1277: BackupSystemLoader ();
1278:
1279: uint64 volumeSize;
1280: uint64 encryptedAreaStart;
1281:
1282: if (systemPartitionOnly)
1283: {
1284: volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart;
1285: encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart;
1286: }
1287: else
1288: {
1289: volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE;
1290: encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE;
1291: }
1292:
1.1.1.3 root 1293: SelectedEncryptionAlgorithmId = ea;
1.1 root 1294: CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5);
1295:
1296: if (!rescueIsoImagePath.empty())
1297: CreateRescueIsoImage (true, rescueIsoImagePath);
1298: }
1299:
1300:
1301: void BootEncryption::StartDecryption ()
1302: {
1303: BootEncryptionStatus encStatus = GetStatus();
1304:
1305: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1306: throw ParameterIncorrect (SRC_POS);
1307:
1308: BootEncryptionSetupRequest request;
1309: ZeroMemory (&request, sizeof (request));
1310:
1311: request.SetupMode = SetupDecryption;
1312:
1313: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
1314: }
1315:
1316:
1317: void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm)
1318: {
1319: BootEncryptionStatus encStatus = GetStatus();
1320:
1321: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1322: throw ParameterIncorrect (SRC_POS);
1323:
1324: BootEncryptionSetupRequest request;
1325: ZeroMemory (&request, sizeof (request));
1326:
1327: request.SetupMode = SetupEncryption;
1328: request.WipeAlgorithm = wipeAlgorithm;
1329:
1330: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
1331: }
1332:
1.1.1.2 root 1333: #endif // !SETUP
1.1 root 1334:
1.1.1.3 root 1335: void BootEncryption::RegisterBootDriver (void)
1336: {
1337: SetDriverServiceStartType (SERVICE_BOOT_START);
1338:
1339: try
1340: {
1341: RegisterFilterDriver (false);
1342: }
1343: catch (...) { }
1344:
1345: RegisterFilterDriver (true);
1346: }
1347:
1348:
1.1 root 1349: bool BootEncryption::RestartComputer (void)
1350: {
1351: TOKEN_PRIVILEGES tokenPrivil;
1352: HANDLE hTkn;
1353:
1354: if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn))
1355: {
1356: return false;
1357: }
1358:
1359: LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid);
1360: tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1361: tokenPrivil.PrivilegeCount = 1;
1362:
1363: AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0);
1364: if (GetLastError() != ERROR_SUCCESS)
1365: return false;
1366:
1367: if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE,
1368: SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
1369: return false;
1370:
1371: return true;
1372: }
1373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.