Annotation of truecrypt/common/bootencryption.cpp, revision 1.1.1.4

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.