|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
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;
499: if (startOnBoot && nCurrentOS != WIN_VISTA_OR_LATER)
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: }
597: partList.push_back (part);
598: }
599:
600: return partList;
601: }
602:
603:
604: DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber)
605: {
606: stringstream devName;
607: devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
608:
609: DISK_GEOMETRY geometry;
610: throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry));
611: return geometry;
612: }
613:
614:
615: string BootEncryption::GetWindowsDirectory ()
616: {
617: char buf[MAX_PATH];
1.1.1.5 root 618: throw_sys_if (GetSystemDirectory (buf, sizeof (buf)) == 0);
619:
620: return string (buf);
1.1 root 621: }
1.1.1.6 ! root 622:
! 623:
! 624: string BootEncryption::GetTempPath ()
! 625: {
! 626: char tempPath[MAX_PATH];
! 627: DWORD tempLen = ::GetTempPath (sizeof (tempPath), tempPath);
! 628: if (tempLen == 0 || tempLen > sizeof (tempPath))
! 629: throw ParameterIncorrect (SRC_POS);
! 630:
! 631: return string (tempPath);
! 632: }
! 633:
1.1 root 634:
635: uint16 BootEncryption::GetInstalledBootLoaderVersion ()
636: {
637: uint16 version;
638: CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version));
639: return version;
640: }
641:
642:
1.1.1.3 root 643: // Note that this does not require admin rights (it just requires the driver to be running)
644: bool BootEncryption::IsBootLoaderOnDrive (char *devicePath)
645: {
646: try
647: {
648: OPEN_TEST_STRUCT openTestStruct;
649: DWORD dwResult;
650:
651: strcpy ((char *) &openTestStruct.wszFileName[0], devicePath);
652: ToUNICODE ((char *) &openTestStruct.wszFileName[0]);
653:
654: openTestStruct.bDetectTCBootLoader = TRUE;
655:
656: return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
657: &openTestStruct, sizeof (OPEN_TEST_STRUCT),
658: NULL, 0,
659: &dwResult, NULL) == TRUE);
660: }
661: catch (...)
662: {
663: return false;
664: }
665: }
666:
667:
1.1 root 668: BootEncryptionStatus BootEncryption::GetStatus ()
669: {
670: /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
671:
672: BootEncryptionStatus status;
673: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status));
674: return status;
675: }
676:
677:
678: void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties)
679: {
680: if (properties == NULL)
681: throw ParameterIncorrect (SRC_POS);
682:
683: CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties));
684: }
685:
686:
1.1.1.5 root 687: bool BootEncryption::IsHiddenSystemRunning ()
688: {
689: int hiddenSystemStatus;
690:
691: CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus));
692: return hiddenSystemStatus != 0;
693: }
694:
695:
1.1.1.2 root 696: bool BootEncryption::SystemDriveContainsPartitionType (byte type)
697: {
698: Device device (GetSystemDriveConfiguration().DevicePath, true);
699:
700: byte mbrBuf[SECTOR_SIZE];
701: device.SeekAt (0);
702: device.Read (mbrBuf, sizeof (mbrBuf));
703:
704: MBR *mbr = reinterpret_cast <MBR *> (mbrBuf);
705: if (mbr->Signature != 0xaa55)
706: throw ParameterIncorrect (SRC_POS);
707:
708: for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i)
709: {
710: if (mbr->Partitions[i].Type == type)
711: return true;
712: }
713:
714: return false;
715: }
716:
717:
718: bool BootEncryption::SystemDriveContainsExtendedPartition ()
719: {
720: return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED);
721: }
722:
723:
724: bool BootEncryption::SystemDriveIsDynamic ()
725: {
1.1.1.5 root 726: GetSystemDriveConfigurationRequest request;
727: _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str());
728:
729: CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
730: return request.DriveIsDynamic ? true : false;
1.1.1.2 root 731: }
732:
733:
1.1 root 734: SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration ()
735: {
736: if (DriveConfigValid)
737: return DriveConfig;
738:
739: SystemDriveConfiguration config;
740:
741: string winDir = GetWindowsDirectory();
742:
743: // Scan all drives
744: for (int driveNumber = 0; driveNumber < 32; ++driveNumber)
745: {
746: bool windowsFound = false;
747: config.SystemLoaderPresent = false;
748:
749: PartitionList partitions = GetDrivePartitions (driveNumber);
750: foreach (const Partition &part, partitions)
751: {
1.1.1.5 root 752: if (!part.MountPoint.empty()
753: && (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0))
754: {
1.1 root 755: config.SystemLoaderPresent = true;
1.1.1.5 root 756: }
1.1 root 757:
1.1.1.6 ! root 758: if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0)
1.1 root 759: {
760: config.SystemPartition = part;
761: windowsFound = true;
762: }
763: }
764:
765: if (windowsFound)
766: {
767: config.DriveNumber = driveNumber;
768:
769: stringstream ss;
770: ss << "PhysicalDrive" << driveNumber;
771: config.DevicePath = ss.str();
772:
1.1.1.5 root 773: stringstream kernelPath;
774: kernelPath << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
775: config.DeviceKernelPath = kernelPath.str();
776:
1.1 root 777: config.DrivePartition = partitions.front();
778: partitions.pop_front();
779: config.Partitions = partitions;
780:
781: config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull;
782: config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart;
783:
784: foreach (const Partition &part, config.Partitions)
785: {
786: if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace)
787: config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart;
788:
789: config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart;
790: }
791:
792: DriveConfig = config;
1.1.1.5 root 793: DriveConfigValid = true;
1.1 root 794: return DriveConfig;
795: }
796: }
797:
798: throw ParameterIncorrect (SRC_POS);
799: }
800:
801:
802: bool BootEncryption::SystemPartitionCoversWholeDrive ()
803: {
804: SystemDriveConfiguration config = GetSystemDriveConfiguration();
805:
806: return config.Partitions.size() == 1
1.1.1.3 root 807: && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB;
1.1 root 808: }
809:
810:
1.1.1.3 root 811: uint32 BootEncryption::GetChecksum (byte *data, size_t size)
1.1 root 812: {
1.1.1.3 root 813: uint32 sum = 0;
814:
815: while (size-- > 0)
816: {
817: sum += *data++;
818: sum = _rotl (sum, 1);
819: }
820:
821: return sum;
822: }
823:
824:
1.1.1.6 ! root 825: void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation)
1.1.1.3 root 826: {
1.1.1.5 root 827: if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE)
1.1.1.3 root 828: throw ParameterIncorrect (SRC_POS);
829:
830: ZeroMemory (buffer, bufferSize);
831:
832: int ea = 0;
833: if (GetStatus().DriveMounted)
834: {
835: try
836: {
837: GetBootEncryptionAlgorithmNameRequest request;
838: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request));
839:
840: if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0)
841: ea = AES;
842: else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
843: ea = SERPENT;
844: else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
845: ea = TWOFISH;
846: }
847: catch (...)
848: {
849: try
850: {
851: VOLUME_PROPERTIES_STRUCT properties;
852: GetVolumeProperties (&properties);
853: ea = properties.ea;
854: }
855: catch (...) { }
856: }
857: }
858: else
859: {
860: if (SelectedEncryptionAlgorithmId == 0)
861: throw ParameterIncorrect (SRC_POS);
862:
863: ea = SelectedEncryptionAlgorithmId;
864: }
865:
1.1.1.5 root 866: int bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR;
867: int bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER;
1.1.1.3 root 868:
869: switch (ea)
870: {
871: case AES:
1.1.1.5 root 872: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES;
873: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES;
1.1.1.3 root 874: break;
875:
876: case SERPENT:
1.1.1.5 root 877: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT;
878: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT;
1.1.1.3 root 879: break;
880:
881: case TWOFISH:
1.1.1.5 root 882: bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH;
883: bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH;
1.1.1.3 root 884: break;
885: }
886:
887: // Boot sector
1.1 root 888: DWORD size;
1.1.1.3 root 889: byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size);
890: if (!bootSecResourceImg || size != SECTOR_SIZE)
891: throw ParameterIncorrect (SRC_POS);
892:
893: memcpy (buffer, bootSecResourceImg, size);
1.1 root 894:
1.1.1.6 ! root 895: *(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM);
! 896:
1.1.1.3 root 897: if (nCurrentOS == WIN_VISTA_OR_LATER)
898: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
899:
1.1.1.6 ! root 900: // Checksum of the backup header of the outer volume for the hidden system
! 901: if (hiddenOSCreation)
! 902: {
! 903: Device device (GetSystemDriveConfiguration().DevicePath);
! 904: byte headerSector[SECTOR_SIZE];
! 905:
! 906: device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE);
! 907: device.Read (headerSector, sizeof (headerSector));
! 908:
! 909: *(uint16 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = (uint16) GetCrc32 (headerSector, sizeof (headerSector));
! 910: }
! 911:
1.1.1.3 root 912: // Decompressor
913: byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size);
914: if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE)
1.1 root 915: throw ParameterIncorrect (SRC_POS);
916:
1.1.1.3 root 917: memcpy (buffer + SECTOR_SIZE, decompressor, size);
1.1 root 918:
1.1.1.3 root 919: // Compressed boot loader
920: byte *bootLoader = MapResource ("BIN", bootLoaderId, &size);
921: if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE)
922: throw ParameterIncorrect (SRC_POS);
1.1 root 923:
1.1.1.3 root 924: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size);
1.1 root 925:
1.1.1.3 root 926: // Boot loader and decompressor checksum
927: *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast <uint16> (size);
928: *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE,
929: TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size);
930:
931: // Backup of decompressor and boot loader
932: if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE)
933: {
934: memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE,
935: buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE);
936:
937: buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE;
938: }
1.1.1.5 root 939: else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER)
1.1.1.3 root 940: {
941: throw ParameterIncorrect (SRC_POS);
942: }
943: }
944:
945:
1.1.1.6 ! root 946: void BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage)
1.1.1.5 root 947: {
1.1.1.6 ! root 948: if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE)
1.1.1.5 root 949: throw ParameterIncorrect (SRC_POS);
950:
951: GetSystemDriveConfigurationRequest request;
952: _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str());
953:
954: try
955: {
956: CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
1.1.1.6 ! root 957: if (config)
! 958: *config = request.Configuration;
! 959:
! 960: if (userConfig)
! 961: *userConfig = request.UserConfiguration;
! 962:
! 963: if (customUserMessage)
! 964: {
! 965: request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0;
! 966: *customUserMessage = request.CustomUserMessage;
! 967: }
1.1.1.5 root 968: }
969: catch (...)
970: {
1.1.1.6 ! root 971: if (config)
! 972: *config = 0;
! 973:
! 974: if (userConfig)
! 975: *userConfig = 0;
! 976:
! 977: if (customUserMessage)
! 978: customUserMessage->clear();
1.1.1.5 root 979: }
980: }
981:
982:
983: void BootEncryption::WriteBootSectorConfig (const byte newConfig[])
984: {
985: Device device (GetSystemDriveConfiguration().DevicePath);
986: byte mbr[SECTOR_SIZE];
987:
988: device.SeekAt (0);
989: device.Read (mbr, sizeof (mbr));
990:
991: memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE);
992:
993: device.SeekAt (0);
994: device.Write (mbr, sizeof (mbr));
995:
996: byte mbrVerificationBuf[SECTOR_SIZE];
997: device.SeekAt (0);
998: device.Read (mbrVerificationBuf, sizeof (mbr));
999:
1000: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
1001: throw ErrorException ("ERROR_MBR_PROTECTED");
1002: }
1003:
1004:
1.1.1.6 ! root 1005: void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage)
! 1006: {
! 1007: Device device (GetSystemDriveConfiguration().DevicePath);
! 1008: byte mbr[SECTOR_SIZE];
! 1009:
! 1010: device.SeekAt (0);
! 1011: device.Read (mbr, sizeof (mbr));
! 1012:
! 1013: mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig;
! 1014:
! 1015: memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
! 1016:
! 1017: if (!customUserMessage.empty())
! 1018: {
! 1019: if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)
! 1020: throw ParameterIncorrect (SRC_POS);
! 1021:
! 1022: memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size());
! 1023: }
! 1024:
! 1025: device.SeekAt (0);
! 1026: device.Write (mbr, sizeof (mbr));
! 1027:
! 1028: byte mbrVerificationBuf[SECTOR_SIZE];
! 1029: device.SeekAt (0);
! 1030: device.Read (mbrVerificationBuf, sizeof (mbr));
! 1031:
! 1032: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
! 1033: throw ErrorException ("ERROR_MBR_PROTECTED");
! 1034: }
! 1035:
! 1036:
1.1.1.5 root 1037: unsigned int BootEncryption::GetHiddenOSCreationPhase ()
1038: {
1039: byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
1040:
1041: ReadBootSectorConfig (configFlags, sizeof(configFlags));
1042:
1043: return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE);
1044: }
1045:
1046:
1047: void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase)
1048: {
1049: #if TC_BOOT_CFG_FLAG_AREA_SIZE != 1
1050: # error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase()
1051: #endif
1052: byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
1053:
1054: ReadBootSectorConfig (configFlags, sizeof(configFlags));
1055:
1056: configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
1057:
1058: configFlags[0] |= newPhase;
1059:
1060: WriteBootSectorConfig (configFlags);
1061: }
1062:
1063:
1.1.1.6 ! root 1064: #ifndef SETUP
! 1065:
! 1066: void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm)
! 1067: {
! 1068: if (!IsHiddenOSRunning())
! 1069: throw ParameterIncorrect (SRC_POS);
! 1070:
! 1071: WipeDecoySystemRequest request;
! 1072: ZeroMemory (&request, sizeof (request));
! 1073:
! 1074: request.WipeAlgorithm = wipeAlgorithm;
! 1075:
! 1076: if (Randinit() != ERR_SUCCESS)
! 1077: throw ParameterIncorrect (SRC_POS);
! 1078:
! 1079: if (!RandgetBytes (request.WipeKey, sizeof (request.WipeKey), TRUE))
! 1080: throw ParameterIncorrect (SRC_POS);
! 1081:
! 1082: CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0);
! 1083:
! 1084: burn (&request, sizeof (request));
! 1085: }
! 1086:
! 1087:
! 1088: void BootEncryption::AbortDecoyOSWipe ()
! 1089: {
! 1090: CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE);
! 1091: }
! 1092:
! 1093:
! 1094: DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus ()
! 1095: {
! 1096: DecoySystemWipeStatus status;
! 1097: CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status));
! 1098: return status;
! 1099: }
! 1100:
! 1101:
! 1102: void BootEncryption::CheckDecoyOSWipeResult ()
! 1103: {
! 1104: CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT);
! 1105: }
! 1106:
! 1107:
! 1108: void BootEncryption::WipeHiddenOSCreationConfig ()
! 1109: {
! 1110: if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS)
! 1111: throw ParameterIncorrect (SRC_POS);
! 1112:
! 1113: Device device (GetSystemDriveConfiguration().DevicePath);
! 1114: byte mbr[SECTOR_SIZE];
! 1115:
! 1116: device.SeekAt (0);
! 1117: device.Read (mbr, sizeof (mbr));
! 1118:
! 1119: finally_do_arg (BootEncryption *, this,
! 1120: {
! 1121: try
! 1122: {
! 1123: finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
! 1124: } catch (...) { }
! 1125: });
! 1126:
! 1127: #if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
! 1128: # error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
! 1129: #endif
! 1130:
! 1131: byte randData[PRAND_DISK_WIPE_PASSES];
! 1132: if (!RandgetBytes (randData, sizeof (randData), FALSE))
! 1133: throw ParameterIncorrect (SRC_POS);
! 1134:
! 1135: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
! 1136: {
! 1137: for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i)
! 1138: {
! 1139: mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass];
! 1140: }
! 1141:
! 1142: mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
! 1143: mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
! 1144:
! 1145: if (wipePass == PRAND_DISK_WIPE_PASSES - 1)
! 1146: memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE);
! 1147:
! 1148: device.SeekAt (0);
! 1149: device.Write (mbr, sizeof (mbr));
! 1150: }
! 1151:
! 1152: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++)
! 1153: {
! 1154: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
! 1155: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING);
! 1156: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING);
! 1157: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED);
! 1158: }
! 1159: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
! 1160: }
! 1161:
! 1162: #endif // !SETUP
! 1163:
! 1164:
! 1165: void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation)
1.1.1.3 root 1166: {
1.1.1.5 root 1167: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE];
1.1.1.6 ! root 1168: CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
1.1.1.3 root 1169:
1170: // Write MBR
1171: Device device (GetSystemDriveConfiguration().DevicePath);
1172: byte mbr[SECTOR_SIZE];
1.1 root 1173:
1174: device.SeekAt (0);
1.1.1.3 root 1175: device.Read (mbr, sizeof (mbr));
1.1 root 1176:
1.1.1.6 ! root 1177: if (preserveUserConfig)
! 1178: {
! 1179: uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
! 1180: if (version != 0)
! 1181: {
! 1182: bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
! 1183: memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
! 1184: }
! 1185: }
! 1186:
1.1.1.3 root 1187: memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
1.1 root 1188:
1.1.1.3 root 1189: device.SeekAt (0);
1190: device.Write (mbr, sizeof (mbr));
1.1 root 1191:
1.1.1.3 root 1192: byte mbrVerificationBuf[SECTOR_SIZE];
1193: device.SeekAt (0);
1194: device.Read (mbrVerificationBuf, sizeof (mbr));
1.1 root 1195:
1.1.1.3 root 1196: if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
1197: throw ErrorException ("ERROR_MBR_PROTECTED");
1.1 root 1198:
1.1.1.3 root 1199: // Write boot loader
1.1 root 1200: device.SeekAt (SECTOR_SIZE);
1.1.1.3 root 1201: device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE);
1.1 root 1202: }
1203:
1204:
1205: string BootEncryption::GetSystemLoaderBackupPath ()
1206: {
1207: char pathBuf[MAX_PATH];
1208:
1209: throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf)));
1210:
1211: string path = string (pathBuf) + "\\" TC_APP_NAME;
1212: CreateDirectory (path.c_str(), NULL);
1213:
1214: return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME;
1215: }
1216:
1.1.1.3 root 1217:
1.1.1.5 root 1218: void BootEncryption::RenameDeprecatedSystemLoaderBackup ()
1219: {
1220: char pathBuf[MAX_PATH];
1221:
1222: if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf)))
1223: {
1224: string path = string (pathBuf) + "\\" TC_APP_NAME + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY;
1225:
1226: if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str()))
1227: throw_sys_if (rename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0);
1228: }
1229: }
1230:
1231:
1.1.1.2 root 1232: #ifndef SETUP
1.1 root 1233: void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath)
1234: {
1235: BootEncryptionStatus encStatus = GetStatus();
1236: if (encStatus.SetupInProgress)
1237: throw ParameterIncorrect (SRC_POS);
1238:
1239: Buffer imageBuf (RescueIsoImageSize);
1240:
1241: byte *image = imageBuf.Ptr();
1242: memset (image, 0, RescueIsoImageSize);
1243:
1244: // Primary volume descriptor
1.1.1.2 root 1245: strcpy ((char *)image + 0x8000, "\001CD001\001");
1246: strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk ");
1247: *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048;
1248: *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048);
1249: image[0x7fff + 121] = 1;
1250: image[0x7fff + 124] = 1;
1251: image[0x7fff + 125] = 1;
1252: image[0x7fff + 128] = 1;
1253: image[0x7fff + 130] = 8;
1254: image[0x7fff + 131] = 8;
1255:
1256: image[0x7fff + 133] = 10;
1257: image[0x7fff + 140] = 10;
1258: image[0x7fff + 141] = 0x14;
1259: image[0x7fff + 157] = 0x22;
1260: image[0x7fff + 159] = 0x18;
1.1 root 1261:
1262: // Boot record volume descriptor
1263: strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION");
1264: image[0x8800 + 0x47] = 0x19;
1265:
1.1.1.2 root 1266: // Volume descriptor set terminator
1267: strcpy ((char *)image + 0x9000, "\377CD001\001");
1268:
1269: // Path table
1270: image[0xA000 + 0] = 1;
1271: image[0xA000 + 2] = 0x18;
1272: image[0xA000 + 6] = 1;
1273:
1274: // Root directory
1275: image[0xc000 + 0] = 0x22;
1276: image[0xc000 + 2] = 0x18;
1277: image[0xc000 + 9] = 0x18;
1278: image[0xc000 + 11] = 0x08;
1279: image[0xc000 + 16] = 0x08;
1280: image[0xc000 + 25] = 0x02;
1281: image[0xc000 + 28] = 0x01;
1282: image[0xc000 + 31] = 0x01;
1283: image[0xc000 + 32] = 0x01;
1284: image[0xc000 + 34] = 0x22;
1285: image[0xc000 + 36] = 0x18;
1286: image[0xc000 + 43] = 0x18;
1287: image[0xc000 + 45] = 0x08;
1288: image[0xc000 + 50] = 0x08;
1289: image[0xc000 + 59] = 0x02;
1290: image[0xc000 + 62] = 0x01;
1291: *(uint32 *) (image + 0xc000 + 65) = 0x010101;
1292:
1.1 root 1293: // Validation entry
1294: image[0xc800] = 1;
1.1.1.2 root 1295: int offset = 0xc800 + 0x1c;
1.1 root 1296: image[offset++] = 0xaa;
1297: image[offset++] = 0x55;
1298: image[offset++] = 0x55;
1299: image[offset] = 0xaa;
1300:
1301: // Initial entry
1302: offset = 0xc820;
1303: image[offset++] = 0x88;
1304: image[offset++] = 2;
1305: image[0xc820 + 6] = 1;
1306: image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR;
1307:
1308: // TrueCrypt Boot Loader
1.1.1.5 root 1309: CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true);
1.1 root 1310:
1311: // Volume header
1312: if (initialSetup)
1313: {
1314: if (!RescueVolumeHeaderValid)
1315: throw ParameterIncorrect (SRC_POS);
1316:
1.1.1.5 root 1317: memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
1.1 root 1318: }
1319: else
1320: {
1321: Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
1322: bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1.1.1.5 root 1323: bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
1.1 root 1324: }
1325:
1326: // Original system loader
1327: try
1328: {
1329: File sysBakFile (GetSystemLoaderBackupPath(), true);
1330: sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE);
1331:
1332: image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER;
1333: }
1334: catch (Exception &e)
1335: {
1336: e.Show (ParentWindow);
1337: Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK");
1338: }
1339:
1.1.1.5 root 1340: // Boot loader backup
1341: CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false);
1342:
1.1 root 1343: RescueIsoImage = new byte[RescueIsoImageSize];
1344: if (!RescueIsoImage)
1345: throw bad_alloc();
1346: memcpy (RescueIsoImage, image, RescueIsoImageSize);
1347:
1348: if (!isoImagePath.empty())
1349: {
1350: File isoFile (isoImagePath, false, true);
1351: isoFile.Write (image, RescueIsoImageSize);
1352: }
1353: }
1.1.1.2 root 1354: #endif
1.1 root 1355:
1356: bool BootEncryption::VerifyRescueDisk ()
1357: {
1358: if (!RescueIsoImage)
1359: throw ParameterIncorrect (SRC_POS);
1360:
1361: for (char drive = 'Z'; drive >= 'D'; --drive)
1362: {
1363: try
1364: {
1365: string path = "X:";
1366: path[0] = drive;
1367:
1368: Device driveDevice (path, true);
1369: size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
1370: Buffer buffer ((verifiedSectorCount + 1) * 2048);
1371:
1372: DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size());
1373: if (bytesRead != buffer.Size())
1374: continue;
1375:
1376: if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
1377: return true;
1378: }
1379: catch (...) { }
1380: }
1381:
1382: return false;
1383: }
1384:
1385:
1386: #ifndef SETUP
1387:
1388: void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5)
1389: {
1390: PCRYPTO_INFO cryptoInfo = NULL;
1.1.1.5 root 1391:
1.1 root 1392: throw_sys_if (Randinit () != 0);
1.1.1.6 ! root 1393: throw_sys_if (CreateVolumeHeaderInMemory (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, &cryptoInfo,
1.1.1.5 root 1394: volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, FALSE) != 0);
1.1 root 1395:
1396: finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); });
1397:
1398: // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
1399: memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
1.1.1.6 ! root 1400: ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo);
1.1 root 1401:
1402: DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
1403:
1404: if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
1405: throw ParameterIncorrect (SRC_POS);
1406:
1407: byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
1408: mputInt64 (fieldPos, volumeSize);
1.1.1.5 root 1409:
1410: // CRC of the header fields
1411: uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
1412: fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC;
1413: mputLong (fieldPos, crc);
1414:
1.1 root 1415: EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
1416:
1417: VolumeHeaderValid = true;
1418: RescueVolumeHeaderValid = true;
1419: }
1420:
1421:
1422: void BootEncryption::InstallVolumeHeader ()
1423: {
1424: if (!VolumeHeaderValid)
1425: throw ParameterIncorrect (SRC_POS);
1426:
1427: Device device (GetSystemDriveConfiguration().DevicePath);
1428:
1429: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1430: device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader));
1431: }
1432:
1433:
1434: // For synchronous operations use AbortSetupWait()
1435: void BootEncryption::AbortSetup ()
1436: {
1437: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
1438: }
1439:
1440:
1441: // For asynchronous operations use AbortSetup()
1442: void BootEncryption::AbortSetupWait ()
1443: {
1444: CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
1445:
1446: BootEncryptionStatus encStatus = GetStatus();
1447:
1448: while (encStatus.SetupInProgress)
1449: {
1450: Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL);
1451: encStatus = GetStatus();
1452: }
1453: }
1454:
1455:
1456: void BootEncryption::BackupSystemLoader ()
1457: {
1458: Device device (GetSystemDriveConfiguration().DevicePath, true);
1459:
1460: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
1461:
1462: device.SeekAt (0);
1463: device.Read (bootLoaderBuf, sizeof (bootLoaderBuf));
1464:
1465: // Prevent TrueCrypt loader from being backed up
1466: for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i)
1467: {
1468: if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
1469: {
1470: if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO)
1471: throw UserAbort (SRC_POS);
1472: return;
1473: }
1474: }
1475:
1476: File backupFile (GetSystemLoaderBackupPath(), false, true);
1477: backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
1478: }
1479:
1480:
1481: void BootEncryption::RestoreSystemLoader ()
1482: {
1483: byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
1484:
1485: File backupFile (GetSystemLoaderBackupPath(), true);
1486:
1487: if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf))
1488: throw ParameterIncorrect (SRC_POS);
1489:
1490: Device device (GetSystemDriveConfiguration().DevicePath);
1.1.1.4 root 1491:
1492: // Preserve current partition table
1493: byte mbr[SECTOR_SIZE];
1494: device.SeekAt (0);
1495: device.Read (mbr, sizeof (mbr));
1496: memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE);
1497:
1.1 root 1498: device.SeekAt (0);
1499: device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
1500: }
1501:
1.1.1.3 root 1502: #endif // SETUP
1.1 root 1503:
1.1.1.5 root 1504: void BootEncryption::RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid)
1.1 root 1505: {
1.1.1.5 root 1506: HKEY classRegKey = SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE);
1.1 root 1507: throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
1508: finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
1509:
1.1.1.5 root 1510: if (registerFilter)
1.1 root 1511: {
1.1.1.5 root 1512: // Register class filter below all other filters in the stack
1513:
1.1 root 1514: size_t strSize = strlen ("truecrypt") + 1;
1515: byte regKeyBuf[65536];
1516: DWORD size = sizeof (regKeyBuf) - strSize;
1517:
1518: // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly
1519: strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf));
1520:
1521: if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS)
1522: size = 1;
1523:
1524: throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS);
1525: }
1526: else
1527: {
1.1.1.5 root 1528: // Unregister a class filter
1.1.1.6 ! root 1529: string infFileName = GetTempPath() + "\\truecrypt_device_filter.inf";
1.1 root 1530:
1531: File infFile (infFileName, false, true);
1.1.1.5 root 1532: finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
1.1 root 1533:
1.1.1.5 root 1534: string infTxt = "[truecrypt]\r\n"
1535: "DelReg=truecrypt_reg\r\n\r\n"
1536: "[truecrypt_reg]\r\n"
1537: "HKR,,\"UpperFilters\",0x00018002,\"truecrypt\"\r\n";
1.1 root 1538:
1539: infFile.Write ((byte *) infTxt.c_str(), infTxt.size());
1540: infFile.Close();
1541:
1542: HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
1543: throw_sys_if (hInf == INVALID_HANDLE_VALUE);
1544: finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
1545:
1546: throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL));
1547: }
1548: }
1.1.1.5 root 1549:
1550: void BootEncryption::RegisterFilterDriver (bool registerDriver, bool volumeClass)
1551: {
1552: if (!IsAdmin() && IsUacSupported())
1553: {
1554: Elevator::RegisterFilterDriver (registerDriver, volumeClass);
1555: return;
1556: }
1557:
1558: if (volumeClass)
1559: {
1560: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_VOLUME);
1561: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_FLOPPYDISK);
1562: }
1563: else
1564: {
1565: RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_DISKDRIVE);
1566: }
1567: }
1.1 root 1568:
1.1.1.3 root 1569: #ifndef SETUP
1.1 root 1570:
1571: void BootEncryption::CheckRequirements ()
1572: {
1573: if (nCurrentOS == WIN_2000)
1574: throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS");
1575:
1576: if (IsNonInstallMode())
1577: throw ErrorException ("FEATURE_REQUIRES_INSTALLATION");
1578:
1579: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1580:
1581: if (config.SystemPartition.IsGPT)
1582: throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED");
1583:
1.1.1.5 root 1584: if (SystemDriveIsDynamic())
1585: throw ErrorException ("SYSENC_UNSUPPORTED_FOR_DYNAMIC_DISK");
1586:
1.1 root 1587: if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE)
1588: throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER");
1589:
1590: DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber);
1591:
1592: if (geometry.BytesPerSector != SECTOR_SIZE)
1593: throw ErrorException ("LARGE_SECTOR_UNSUPPORTED");
1594:
1595: if (!config.SystemLoaderPresent)
1596: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
1.1.1.5 root 1597:
1598: if (!config.SystemPartition.IsGPT)
1599: {
1600: // Determine whether there is an Active partition on the system drive
1601: bool activePartitionFound = false;
1602: foreach (const Partition &partition, config.Partitions)
1603: {
1604: if (partition.Info.BootIndicator)
1605: {
1606: activePartitionFound = true;
1607: break;
1608: }
1609: }
1610:
1611: if (!activePartitionFound)
1612: throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
1613: }
1614: }
1615:
1616:
1617: void BootEncryption::CheckRequirementsHiddenOS ()
1618: {
1619: // It is assumed that CheckRequirements() had been called (so we don't check e.g. whether it's GPT).
1620:
1621: // The user may have modified/added/deleted partitions since the partition table was last scanned.
1622: InvalidateCachedSysDriveProperties ();
1623:
1624: GetPartitionForHiddenOS ();
1.1 root 1625: }
1626:
1627:
1.1.1.6 ! root 1628: void BootEncryption::InitialSecurityChecksForHiddenOS ()
! 1629: {
! 1630: char windowsDrive = toupper (GetWindowsDirectory()[0]);
! 1631:
! 1632: // Paging files
! 1633: if (IsPagingFileActive (TRUE))
! 1634: {
! 1635: throw ErrorException (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION"))
! 1636: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION"));
! 1637: }
! 1638:
! 1639: char pagingFileRegData[65536];
! 1640: DWORD pagingFileRegDataSize = sizeof (pagingFileRegData);
! 1641:
! 1642: if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFileRegData, &pagingFileRegDataSize)
! 1643: && pagingFileRegDataSize > 4)
! 1644: {
! 1645: for (size_t i = 1; i < pagingFileRegDataSize - 2; ++i)
! 1646: {
! 1647: if (memcmp (pagingFileRegData + i, ":\\", 2) == 0 && toupper (pagingFileRegData[i - 1]) != windowsDrive)
! 1648: {
! 1649: throw ErrorException (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION"))
! 1650: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION"));
! 1651: }
! 1652: }
! 1653: }
! 1654:
! 1655: // User profile
! 1656: char *configPath = GetConfigPath ("dummy");
! 1657: if (configPath && toupper (configPath[0]) != windowsDrive)
! 1658: {
! 1659: throw ErrorException (wstring (GetString ("USER_PROFILE_NOT_ON_SYS_PARTITION"))
! 1660: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION"));
! 1661: }
! 1662:
! 1663: // Temporary files
! 1664: if (toupper (GetTempPath()[0]) != windowsDrive)
! 1665: {
! 1666: throw ErrorException (wstring (GetString ("TEMP_NOT_ON_SYS_PARTITION"))
! 1667: + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION"));
! 1668: }
! 1669: }
! 1670:
! 1671:
1.1 root 1672: void BootEncryption::Deinstall ()
1673: {
1674: BootEncryptionStatus encStatus = GetStatus();
1675:
1676: if (encStatus.DriveEncrypted || encStatus.DriveMounted)
1677: throw ParameterIncorrect (SRC_POS);
1678:
1679: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1680:
1681: if (encStatus.VolumeHeaderPresent)
1682: {
1683: // Verify CRC of header salt
1684: Device device (config.DevicePath, true);
1.1.1.5 root 1685: byte header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE];
1.1 root 1686:
1687: device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
1688: device.Read (header, sizeof (header));
1689:
1690: if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE))
1691: throw ParameterIncorrect (SRC_POS);
1692: }
1693:
1.1.1.5 root 1694: RegisterFilterDriver (false, false);
1695: RegisterFilterDriver (false, true);
1.1 root 1696: SetDriverServiceStartType (SERVICE_SYSTEM_START);
1697:
1.1.1.5 root 1698: SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); // In case RestoreSystemLoader() fails
1699:
1.1 root 1700: try
1701: {
1702: RestoreSystemLoader ();
1703: }
1704: catch (Exception &e)
1705: {
1706: e.Show (ParentWindow);
1707: throw ErrorException ("SYS_LOADER_RESTORE_FAILED");
1708: }
1709: }
1710:
1711:
1712: int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5)
1713: {
1.1.1.5 root 1714: BootEncryptionStatus encStatus = GetStatus();
1715:
1716: if (encStatus.SetupInProgress)
1.1 root 1717: throw ParameterIncorrect (SRC_POS);
1718:
1719: SystemDriveConfiguration config = GetSystemDriveConfiguration ();
1720:
1.1.1.5 root 1721: char header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE];
1.1 root 1722: Device device (config.DevicePath);
1723:
1724: // Only one algorithm is currently supported
1725: if (pkcs5 != 0)
1726: throw ParameterIncorrect (SRC_POS);
1727:
1.1.1.5 root 1728: int64 headerOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
1729: int64 backupHeaderOffset = -1;
1730:
1731: if (encStatus.HiddenSystem)
1732: {
1733: headerOffset = encStatus.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
1734:
1735: // Find hidden system partition
1736: foreach (const Partition &partition, config.Partitions)
1737: {
1738: if (partition.Info.StartingOffset.QuadPart == encStatus.HiddenSystemPartitionStart)
1739: {
1740: backupHeaderOffset = partition.Info.StartingOffset.QuadPart + partition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_SIZE;
1741: break;
1742: }
1743: }
1744:
1745: if (backupHeaderOffset == -1)
1746: throw ParameterIncorrect (SRC_POS);
1747: }
1748:
1749: device.SeekAt (headerOffset);
1.1 root 1750: device.Read ((byte *) header, sizeof (header));
1751:
1752: PCRYPTO_INFO cryptoInfo = NULL;
1753:
1.1.1.6 ! root 1754: int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, &cryptoInfo, NULL);
1.1 root 1755: finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
1756:
1757: if (status != 0)
1758: {
1759: handleError (ParentWindow, status);
1760: return status;
1761: }
1762:
1763: // Change the PKCS-5 PRF if requested by user
1764: if (pkcs5 != 0)
1765: cryptoInfo->pkcs5 = pkcs5;
1766:
1767: throw_sys_if (Randinit () != 0);
1768:
1769: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
1770: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
1771: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
1772: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
1773: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
1774: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
1775: recommends. During each pass we will write a valid working header. Each pass will use the same master
1776: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
1777: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
1778: of the header to differ substantially and in a random manner from the versions written during the
1779: other passes. */
1780:
1781: bool headerUpdated = false;
1782: int result = ERR_SUCCESS;
1783:
1784: try
1785: {
1.1.1.5 root 1786: BOOL backupHeader = FALSE;
1787: while (TRUE)
1.1 root 1788: {
1.1.1.5 root 1789: for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
1.1 root 1790: {
1.1.1.5 root 1791: PCRYPTO_INFO tmpCryptoInfo = NULL;
1792:
1.1.1.6 ! root 1793: status = CreateVolumeHeaderInMemory (!encStatus.HiddenSystem,
1.1.1.5 root 1794: header,
1795: cryptoInfo->ea,
1796: cryptoInfo->mode,
1797: newPassword,
1798: cryptoInfo->pkcs5,
1799: (char *) cryptoInfo->master_keydata,
1800: &tmpCryptoInfo,
1801: cryptoInfo->VolumeSize.Value,
1802: cryptoInfo->hiddenVolumeSize,
1803: cryptoInfo->EncryptedAreaStart.Value,
1804: cryptoInfo->EncryptedAreaLength.Value,
1805: cryptoInfo->RequiredProgramVersion,
1806: cryptoInfo->HeaderFlags | TC_HEADER_FLAG_ENCRYPTED_SYSTEM,
1807: wipePass < PRAND_DISK_WIPE_PASSES - 1);
1808:
1809: if (tmpCryptoInfo)
1810: crypto_close (tmpCryptoInfo);
1811:
1812: if (status != 0)
1813: {
1814: handleError (ParentWindow, status);
1815: return status;
1816: }
1817:
1818: device.SeekAt (headerOffset);
1819: device.Write ((byte *) header, sizeof (header));
1820: headerUpdated = true;
1.1 root 1821: }
1822:
1.1.1.5 root 1823: if (!encStatus.HiddenSystem || backupHeader)
1824: break;
1825:
1826: backupHeader = TRUE;
1827: headerOffset = backupHeaderOffset;
1.1 root 1828: }
1829: }
1830: catch (Exception &e)
1831: {
1832: e.Show (ParentWindow);
1833: result = ERR_OS_ERROR;
1834: }
1835:
1836: if (headerUpdated)
1837: {
1838: ReopenBootVolumeHeaderRequest reopenRequest;
1839: reopenRequest.VolumePassword = *newPassword;
1840: finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); });
1841:
1842: CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
1843: }
1844:
1845: return result;
1846: }
1847:
1848:
1849: void BootEncryption::CheckEncryptionSetupResult ()
1850: {
1.1.1.6 ! root 1851: try
! 1852: {
! 1853: CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
! 1854: }
! 1855: catch (SystemException &e)
! 1856: {
! 1857: // Encryption of the whole drive may for some reason end with "incorrect function" (STATUS_NOT_IMPLEMENTED) error
! 1858: if (e.ErrorCode == STATUS_NONCONTINUABLE_EXCEPTION
! 1859: && GetStatus().ConfiguredEncryptedAreaEnd + 1 >= GetSystemDriveConfiguration().DrivePartition.Info.PartitionLength.QuadPart)
! 1860: {
! 1861: SetLastError (ERROR_INVALID_FUNCTION);
! 1862: handleWin32Error (NULL);
! 1863: Error ("WHOLE_DRIVE_ENCRYPTION_FAILED");
! 1864: throw UserAbort (SRC_POS);
! 1865: }
! 1866:
! 1867: throw;
! 1868: }
1.1 root 1869: }
1870:
1871:
1.1.1.6 ! root 1872: void BootEncryption::Install (bool hiddenSystem)
1.1 root 1873: {
1874: BootEncryptionStatus encStatus = GetStatus();
1875: if (encStatus.DriveMounted)
1876: throw ParameterIncorrect (SRC_POS);
1877:
1878: try
1879: {
1.1.1.6 ! root 1880: InstallBootLoader (false, hiddenSystem);
! 1881:
! 1882: if (!hiddenSystem)
! 1883: InstallVolumeHeader ();
! 1884:
! 1885: RegisterBootDriver (hiddenSystem);
1.1 root 1886:
1.1.1.3 root 1887: // Prevent system log errors caused by rejecting crash dumps
1888: WriteLocalMachineRegistryDword ("System\\CurrentControlSet\\Control\\CrashControl", "CrashDumpEnabled", 0);
1.1 root 1889: }
1890: catch (Exception &)
1891: {
1892: try
1893: {
1894: RestoreSystemLoader ();
1895: }
1896: catch (Exception &e)
1897: {
1898: e.Show (ParentWindow);
1899: }
1900:
1901: throw;
1902: }
1903: }
1904:
1905:
1.1.1.6 ! root 1906: void BootEncryption::PrepareHiddenOSCreation (int ea, int mode, int pkcs5)
! 1907: {
! 1908: BootEncryptionStatus encStatus = GetStatus();
! 1909: if (encStatus.DriveMounted)
! 1910: throw ParameterIncorrect (SRC_POS);
! 1911:
! 1912: CheckRequirements();
! 1913: BackupSystemLoader();
! 1914:
! 1915: SelectedEncryptionAlgorithmId = ea;
! 1916: }
! 1917:
! 1918:
1.1 root 1919: void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath)
1920: {
1921: BootEncryptionStatus encStatus = GetStatus();
1922: if (encStatus.DriveMounted)
1923: throw ParameterIncorrect (SRC_POS);
1924:
1925: CheckRequirements ();
1926:
1927: SystemDriveConfiguration config = GetSystemDriveConfiguration();
1928: BackupSystemLoader ();
1929:
1930: uint64 volumeSize;
1931: uint64 encryptedAreaStart;
1932:
1933: if (systemPartitionOnly)
1934: {
1935: volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart;
1936: encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart;
1937: }
1938: else
1939: {
1940: volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE;
1941: encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE;
1942: }
1943:
1.1.1.3 root 1944: SelectedEncryptionAlgorithmId = ea;
1.1 root 1945: CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5);
1946:
1947: if (!rescueIsoImagePath.empty())
1948: CreateRescueIsoImage (true, rescueIsoImagePath);
1949: }
1950:
1951:
1.1.1.6 ! root 1952: bool BootEncryption::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly)
1.1.1.5 root 1953: {
1954: if (!IsAdmin() && IsUacSupported())
1.1.1.6 ! root 1955: return Elevator::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false;
1.1.1.5 root 1956:
1.1.1.6 ! root 1957: return ::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false;
1.1.1.5 root 1958: }
1959:
1960:
1961: void BootEncryption::WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value)
1962: {
1963: if (!IsAdmin() && IsUacSupported())
1964: {
1965: Elevator::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value);
1966: return;
1967: }
1968:
1969: throw_sys_if (!WriteLocalMachineRegistryDword (keyPath, valueName, value));
1970: }
1971:
1972:
1.1 root 1973: void BootEncryption::StartDecryption ()
1974: {
1975: BootEncryptionStatus encStatus = GetStatus();
1976:
1977: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1978: throw ParameterIncorrect (SRC_POS);
1979:
1980: BootEncryptionSetupRequest request;
1981: ZeroMemory (&request, sizeof (request));
1982:
1983: request.SetupMode = SetupDecryption;
1984:
1985: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
1986: }
1987:
1988:
1.1.1.6 ! root 1989: void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors)
1.1 root 1990: {
1991: BootEncryptionStatus encStatus = GetStatus();
1992:
1993: if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
1994: throw ParameterIncorrect (SRC_POS);
1995:
1996: BootEncryptionSetupRequest request;
1997: ZeroMemory (&request, sizeof (request));
1998:
1999: request.SetupMode = SetupEncryption;
2000: request.WipeAlgorithm = wipeAlgorithm;
1.1.1.6 ! root 2001: request.ZeroUnreadableSectors = zeroUnreadableSectors;
1.1 root 2002:
2003: CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
2004: }
2005:
1.1.1.2 root 2006: #endif // !SETUP
1.1 root 2007:
1.1.1.6 ! root 2008:
! 2009: void BootEncryption::WriteBootDriveSector (uint64 offset, byte *data)
! 2010: {
! 2011: WriteBootDriveSectorRequest request;
! 2012: request.Offset.QuadPart = offset;
! 2013: memcpy (request.Data, data, sizeof (request.Data));
! 2014:
! 2015: CallDriver (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR, &request, sizeof (request), NULL, 0);
! 2016: }
! 2017:
! 2018:
! 2019: void BootEncryption::RegisterBootDriver (bool hiddenSystem)
1.1.1.3 root 2020: {
2021: SetDriverServiceStartType (SERVICE_BOOT_START);
2022:
2023: try
2024: {
1.1.1.5 root 2025: RegisterFilterDriver (false, false);
2026: RegisterFilterDriver (false, true);
1.1.1.3 root 2027: }
2028: catch (...) { }
2029:
1.1.1.5 root 2030: RegisterFilterDriver (true, false);
1.1.1.6 ! root 2031:
! 2032: if (hiddenSystem)
! 2033: RegisterFilterDriver (true, true);
1.1.1.3 root 2034: }
2035:
2036:
1.1 root 2037: bool BootEncryption::RestartComputer (void)
2038: {
1.1.1.5 root 2039: return (::RestartComputer() != FALSE);
1.1 root 2040: }
2041: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.