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