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