Annotation of truecrypt/boot/windows/bootmain.cpp, revision 1.1.1.2

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 "Crc.h"
                     10: #include "Crypto.h"
                     11: #include "Password.h"
                     12: #include "Volumes.h"
                     13: 
                     14: #include "Platform.h"
                     15: #include "Bios.h"
                     16: #include "BootConfig.h"
                     17: #include "BootMain.h"
                     18: #include "BootDefs.h"
                     19: #include "BootCommon.h"
                     20: #include "BootConsoleIo.h"
                     21: #include "BootDebug.h"
                     22: #include "BootDiskIo.h"
                     23: #include "BootEncryptedIo.h"
1.1.1.2 ! root       24: #include "BootMemory.h"
1.1       root       25: #include "IntFilter.h"
                     26: 
                     27: 
                     28: static void InitScreen ()
                     29: {
                     30:        ClearScreen();
                     31: 
                     32:        Print (" TrueCrypt Boot Loader " VERSION_STRING "             Copyright (C) 2008 TrueCrypt Foundation\r\n");
                     33:        PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE);
                     34: 
                     35:        PrintEndl (2);
                     36: }
                     37: 
                     38: 
                     39: static void PrintMainMenu ()
                     40: {
                     41:        Print ("    Keyboard Controls:\r\n");
                     42:        Print ("    [Esc]  Skip Authentication (Boot Manager)\r\n");
                     43:        Print ("    [F8]   "); Print ("Repair Options");
                     44: 
                     45:        PrintEndl (3);
                     46: }
                     47: 
                     48: 
                     49: static bool IsMenuKey (byte scanCode)
                     50: {
                     51:        return scanCode == TC_MENU_KEY_REPAIR;
                     52: }
                     53: 
                     54: 
                     55: static bool AskYesNo (const char *message)
                     56: {
                     57:        Print (message);
                     58:        Print ("? (y/n): ");
                     59:        while (true)
                     60:        {
                     61:                switch (GetKeyboardChar())
                     62:                {
                     63:                case 'y':
                     64:                case 'Y':
                     65:                        PrintEndl();
                     66:                        return true;
                     67: 
                     68:                case 'n':
                     69:                case 'N':
                     70:                        PrintEndl();
                     71:                        return false;
                     72: 
                     73:                default:
                     74:                        Beep();
                     75:                }
                     76:        }
                     77: }
                     78: 
                     79: 
                     80: static int AskSelection (const char *options[], size_t optionCount)
                     81: {
                     82:        for (int i = 0; i < optionCount; ++i)
                     83:        {
                     84:                Print ("["); Print (i + 1); Print ("]    ");
                     85:                Print (options[i]);
                     86:                PrintEndl();
                     87:        }
                     88:        Print ("[Esc]  Cancel\r\n\r\n");
                     89: 
                     90:        Print ("To select, press 1-9: ");
                     91: 
                     92:        char str;
                     93: 
                     94:        while (true)
                     95:        {
                     96:                if (GetString (&str, 1) == 0)
                     97:                        return 0;
                     98: 
                     99:                if (str >= '1' && str <= optionCount + '0')
                    100:                        return str - '0';
                    101: 
                    102:                Beep();
                    103:                PrintBackspace();
                    104:        }
                    105: }
                    106: 
                    107: 
                    108: static byte AskPassword (Password &password)
                    109: {
                    110:        size_t pos = 0;
                    111:        byte scanCode;
                    112:        byte asciiCode;
                    113: 
                    114:        Print ("Enter password: ");
                    115: 
                    116:        while (true)
                    117:        {
                    118:                asciiCode = GetKeyboardChar (&scanCode);
                    119: 
                    120:                switch (scanCode)
                    121:                {
                    122:                case TC_BIOS_KEY_ENTER:
1.1.1.2 ! root      123:                        ClearBiosKeystrokeBuffer();
1.1       root      124:                        PrintEndl();
1.1.1.2 ! root      125: 
        !           126:                        password.Length = pos;
        !           127:                        return scanCode;
1.1       root      128: 
                    129:                case TC_BIOS_KEY_BACKSPACE:
                    130:                        if (pos > 0)
                    131:                        {
                    132:                                if (pos < MAX_PASSWORD)
                    133:                                        PrintBackspace();
                    134:                                else
                    135:                                        PrintCharAtCusor (' ');
                    136: 
                    137:                                --pos;
                    138:                        }
                    139:                        continue;
                    140: 
                    141:                default:
                    142:                        if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode))
                    143:                        {
                    144:                                burn (password.Text, sizeof (password.Text));
1.1.1.2 ! root      145:                                ClearBiosKeystrokeBuffer();
        !           146: 
1.1       root      147:                                PrintEndl();
                    148:                                return scanCode;
                    149:                        }
                    150:                }
                    151: 
                    152:                if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD)
                    153:                {
                    154:                        Beep();
                    155:                        continue;
                    156:                }
                    157: 
                    158:                password.Text[pos++] = asciiCode;
                    159:                if (pos < MAX_PASSWORD)
                    160:                        PrintChar ('*');
                    161:                else
                    162:                        PrintCharAtCusor ('*');
                    163:        }
                    164: }
                    165: 
                    166: 
                    167: static void ExecuteBootSector (byte drive, byte *sectorBuffer)
                    168: {
                    169:        Print ("Booting...\r\n");
                    170:        CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE);
                    171:        Jump (0x0000, 0x7c00, drive);
                    172: }
                    173: 
                    174: 
                    175: static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headSaltCrc32)
                    176: {
                    177:        byte header[HEADER_SIZE];
                    178:        uint64 headerSec;
                    179:        headerSec.HighPart = 0;
                    180:        headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
                    181: 
                    182:        if (ReadSectors (header, drive, headerSec, 1) != BiosResultSuccess)
                    183:                return false;
                    184: 
                    185:        if (VolumeReadHeader (TRUE, (char *) header, &password, cryptoInfo, nullptr) == 0)
                    186:        {
                    187:                if (headSaltCrc32)
                    188:                        *headSaltCrc32 = GetCrc32 (header, PKCS5_SALT_SIZE);
                    189:                return true;
                    190:        }
                    191: 
                    192:        return false;
                    193: }
                    194: 
                    195: 
1.1.1.2 ! root      196: static bool CheckMemoryRequirements ()
        !           197: {
        !           198:        uint16 codeSeg;
        !           199:        __asm mov codeSeg, cs
        !           200:        if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT)
        !           201:        {
        !           202:                PrintError ("Insufficient base memory: ", true, false);
        !           203: 
        !           204:                uint16 memFree;
        !           205:                __asm
        !           206:                {
        !           207:                        push es
        !           208:                        xor ax, ax
        !           209:                        mov es, ax
        !           210:                        mov ax, es:[0x413]
        !           211:                        mov memFree, ax
        !           212:                        pop es
        !           213:                }
        !           214: 
        !           215:                Print (memFree); Print (" KB\r\n");
        !           216: 
        !           217:                return false;
        !           218:        }
        !           219: 
        !           220:        // Check for conflicts with BIOS memory map
        !           221:        uint64 bootLoaderStart;
        !           222:        bootLoaderStart.HighPart = 0;
        !           223:        bootLoaderStart.LowPart = GetLinearAddress (codeSeg, 0);
        !           224: 
        !           225:        BiosMemoryMapEntry entry;
        !           226:        if (GetFirstBiosMemoryMapEntry (entry))
        !           227:        {
        !           228:                do
        !           229:                {
        !           230:                        if (entry.Type != 0x1
        !           231:                                && RegionsIntersect (bootLoaderStart, TC_BOOT_MEMORY_REQUIRED * 1024UL, entry.BaseAddress, entry.BaseAddress + entry.Length - 1))
        !           232:                        {
        !           233:                                PrintError ("Your BIOS reserved a memory area required by TrueCrypt:");
        !           234:                                Print ("Type:"); Print (entry.Type);
        !           235:                                Print (" Start:"); PrintHex (entry.BaseAddress);
        !           236:                                Print (" Length:"); PrintHex (entry.Length);
        !           237:                                PrintEndl (2);
        !           238: 
        !           239:                                return false;
        !           240:                        }
        !           241:                }
        !           242:                while (GetNextBiosMemoryMapEntry (entry));
        !           243:        }
        !           244: 
        !           245:        return true;
        !           246: }
        !           247: 
        !           248: 
1.1       root      249: static bool MountVolume (byte drive, byte &exitKey)
                    250: {
                    251:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
                    252: 
                    253:        // Open volume header
                    254:        while (true)
                    255:        {
                    256:                exitKey = AskPassword (bootArguments->BootPassword);
                    257: 
                    258:                if (exitKey != TC_BIOS_KEY_ENTER)
                    259:                        return false;
                    260: 
                    261:                if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32))
                    262:                        break;
                    263: 
                    264:                Print ("Incorrect password or not a TrueCrypt volume.\r\n\r\n");
                    265:        }
                    266: 
                    267:        // Setup boot arguments
                    268:        bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo;
                    269:        bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo);
                    270:        bootArguments->BootLoaderVersion = VERSION_NUM;
                    271:        TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature);
                    272: 
                    273:        if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0)
                    274:        {
                    275:                // Setup virtual encrypted partition
                    276:                EncryptedVirtualPartition.Drive = BootDrive;
                    277: 
                    278:                EncryptedVirtualPartition.StartSector.HighPart = BootCryptoInfo->EncryptedAreaStart.HighPart;
                    279:                EncryptedVirtualPartition.StartSector.LowPart = BootCryptoInfo->EncryptedAreaStart.LowPart;
                    280:                EncryptedVirtualPartition.StartSector = EncryptedVirtualPartition.StartSector >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    281: 
                    282:                EncryptedVirtualPartition.EndSector.HighPart = BootCryptoInfo->EncryptedAreaLength.HighPart;
                    283:                EncryptedVirtualPartition.EndSector.LowPart = BootCryptoInfo->EncryptedAreaLength.LowPart;
                    284:                EncryptedVirtualPartition.EndSector = (EncryptedVirtualPartition.EndSector - 1) >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    285:                EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.EndSector + EncryptedVirtualPartition.StartSector;
                    286:        }
                    287:        else
                    288:        {
                    289:                // Drive not encrypted
                    290:                EncryptedVirtualPartition.Drive = TC_FIRST_BIOS_DRIVE - 1;
                    291:        }
                    292: 
                    293:        return true;
                    294: }
                    295: 
                    296: 
                    297: static byte BootEncryptedDrive ()
                    298: {
                    299:        Partition partition;
                    300:        size_t partCount;
                    301: 
                    302:        // Find active partition
                    303:        if (GetActivePartition (BootDrive, partition, partCount, false) != BiosResultSuccess || partCount < 1)
                    304:        {
                    305:                PrintError ("No bootable partition found");
                    306:                goto err;
                    307:        }
                    308: 
                    309:        byte exitKey;
                    310:        if (!MountVolume (BootDrive, exitKey))
                    311:                return exitKey;
                    312:        
1.1.1.2 ! root      313:        if (!CheckMemoryRequirements ())
        !           314:        {
        !           315:                Print ("Try disabling unneeded components (RAID, AHCI, integrated audio card, etc.) in\r\n"
        !           316:                                "BIOS setup menu (invoked by pressing Del or F2 after turning on your computer).\r\n");
        !           317:                goto err;
        !           318:        }
        !           319: 
        !           320:        if (!InstallInterruptFilters())
        !           321:                goto err;
1.1       root      322: 
                    323:        // Execute boot sector of the active partition
                    324:        byte bootSector[TC_LB_SIZE];
                    325:        if (ReadSectors (bootSector, partition.Drive, partition.StartSector, 1) == BiosResultSuccess)
                    326:        {
                    327:                ExecuteBootSector (partition.Drive, bootSector);
                    328:        }
                    329: 
                    330: err:
1.1.1.2 ! root      331:        EncryptedVirtualPartition.Drive = TC_FIRST_BIOS_DRIVE - 1;
        !           332:        memset ((void *) TC_BOOT_LOADER_ARGS_OFFSET, 0, sizeof (BootArguments));
        !           333: 
1.1       root      334:        byte scanCode;
                    335:        GetKeyboardChar (&scanCode);
                    336:        return scanCode;
                    337: }
                    338: 
                    339: 
                    340: static void BootMenu ()
                    341: {
                    342:        BiosResult result;
                    343:        Partition partitions[16];
                    344:        Partition bootablePartitions[9];
                    345:        size_t partitionCount;
                    346:        size_t bootablePartitionCount = 0;
                    347: 
                    348:        for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive)
                    349:        {
                    350:                if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, true) == BiosResultSuccess)
                    351:                {
                    352:                        for (size_t i = 0; i < partitionCount; ++i)
                    353:                        {
                    354:                                const Partition &partition = partitions[i];
                    355: 
                    356:                                byte bootSector[TC_LB_SIZE];
                    357:                                result = ReadSectors (bootSector, drive, partition.StartSector, 1);
                    358: 
                    359:                                if (result == BiosResultSuccess && *(uint16 *) (bootSector + TC_LB_SIZE - 2) == 0xaa55)
                    360:                                {
                    361:                                        // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore,
                    362:                                        // NTFS/FAT partitions must have the boot indicator set to be considered bootable.
                    363:                                        if (!partition.Active
                    364:                                                && (*(uint32 *) (bootSector + 3) == 0x5346544e  // 'NTFS'
                    365:                                                        || *(uint16 *) (bootSector + 54) == 0x4146 && bootSector[56] == 'T' // 'FAT'
                    366:                                                        || *(uint16 *) (bootSector + 82) == 0x4146 && bootSector[84] == 'T'))
                    367:                                        {
                    368:                                                continue;
                    369:                                        }
                    370: 
                    371:                                        // Bootable sector found
                    372:                                        if (bootablePartitionCount < array_capacity (bootablePartitions))
                    373:                                                bootablePartitions[bootablePartitionCount++] = partition;
                    374:                                }
                    375:                        }
                    376:                }
                    377:        }
                    378: 
                    379:        if (bootablePartitionCount < 1)
                    380:        {
                    381:                PrintError ("No bootable partition found");
                    382:                GetKeyboardChar();
                    383:                return;
                    384:        }
                    385: 
                    386:        char partChar;
                    387:        while (true)
                    388:        {
                    389:                InitScreen();
                    390:                Print ("Bootable Partitions:\r\n");
                    391:                PrintRepeatedChar ('\xC4', 20);
                    392:                Print ("\r\n");
                    393: 
                    394:                for (size_t i = 0; i < bootablePartitionCount; ++i)
                    395:                {
                    396:                        const Partition &partition = bootablePartitions[i];
                    397:                        Print ("["); Print (i + 1); Print ("]    ");
                    398:                        Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE);
                    399:                        Print (", Partition: "); Print (partition.Number + 1);
                    400:                        Print (", Size: "); Print (partition.SectorCount >> 11); Print (" MB\r\n");
                    401:                }
                    402: 
                    403:                if (bootablePartitionCount == 1)
                    404:                {
                    405:                        // There's only one bootable partition so we'll boot it directly instead of showing boot manager
                    406:                        partChar = '1';
                    407:                }
                    408:                else
                    409:                {
                    410:                        Print ("[Esc]  Cancel\r\n\r\n");
                    411:                        Print ("Press 1-9 to select partition: ");
                    412: 
                    413:                        if (GetString (&partChar, 1) == 0)
                    414:                                return;
                    415: 
                    416:                        PrintEndl();
                    417: 
                    418:                        if (partChar < '1' || partChar > '0' + bootablePartitionCount)
                    419:                        {
                    420:                                Beep();
                    421:                                continue;
                    422:                        }
                    423:                }
                    424: 
                    425:                const Partition &partition = bootablePartitions[partChar - '0' - 1];
                    426: 
                    427:                byte bootSector[TC_LB_SIZE];
                    428:                if (ReadSectors (bootSector, partition.Drive, partition.StartSector, 1) == BiosResultSuccess)
                    429:                {
                    430:                        ExecuteBootSector (partition.Drive, bootSector);
                    431:                }
                    432:        }
                    433: }
                    434: 
                    435: 
                    436: static void DecryptDrive (byte drive)
                    437: {
                    438:        byte exitKey;
                    439:        if (!MountVolume (drive, exitKey))
                    440:                return;
                    441: 
                    442:        const int sectorsPerIoBlock = 0x7f; // Maximum safe value supported by BIOS
                    443: 
                    444:        bool headerUpdateRequired = false;
                    445:        uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector;
                    446:        uint64 sector = EncryptedVirtualPartition.EndSector + 1;
                    447: 
                    448:        byte sectorBuf[TC_LB_SIZE];
                    449:        int fragmentSectorCount = sectorsPerIoBlock;
                    450:        int statCount;
                    451: 
                    452:        if (EncryptedVirtualPartition.Drive == TC_FIRST_BIOS_DRIVE - 1)
                    453:        {
                    454:                // Drive not encrypted
                    455:                sectorsRemaining.HighPart = 0;
                    456:                sectorsRemaining.LowPart = 0;
                    457:                headerUpdateRequired = true;
                    458:        }
                    459:        else
                    460:        {
                    461:                Print ("\r\nDo NOT turn off power. Press ESC to abort.\r\n");
                    462:        }
                    463: 
                    464:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
                    465:        {
                    466:                if (IsKeyboardCharAvailable ())
                    467:                {
                    468:                        byte keyScanCode;
                    469:                        GetKeyboardChar (&keyScanCode);
                    470:                        if (keyScanCode == TC_BIOS_KEY_ESC)
                    471:                                break;
                    472:                }
                    473: 
                    474:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
                    475:                        fragmentSectorCount = sectorsRemaining.LowPart;
                    476: 
                    477:                sector = sector - fragmentSectorCount;
                    478: 
                    479:                if (!(statCount++ & 0xf))
                    480:                {
                    481:                        Print ("\rRemaining: ");
                    482:                        Print (sectorsRemaining >> 11); Print (" MB ");
                    483:                }
                    484: 
                    485:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, false) != BiosResultSuccess)
                    486:                        break;
                    487: 
                    488:                for (int i = 0; i < fragmentSectorCount; ++i)
                    489:                {
                    490:                        CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * sizeof (sectorBuf), sectorBuf, sizeof (sectorBuf));
                    491: 
                    492:                        uint64 s = sector + i;
                    493:                        DecryptDataUnits (sectorBuf, &s, 1, BootCryptoInfo);
                    494: 
                    495:                        CopyMemory (sectorBuf, TC_BOOT_LOADER_BUFFER_SEGMENT, i * sizeof (sectorBuf), sizeof (sectorBuf));
                    496:                } 
                    497: 
                    498:                if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, false) != BiosResultSuccess)
                    499:                        break;
                    500: 
                    501:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
                    502:                headerUpdateRequired = true;
                    503:        }
                    504: 
                    505:        crypto_close (BootCryptoInfo);
                    506:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
                    507: 
                    508:        if (headerUpdateRequired)
                    509:        {
                    510:                byte header[HEADER_SIZE];
                    511:                uint64 headerSector;
                    512:                headerSector.HighPart = 0;
                    513:                headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
                    514: 
                    515:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
                    516:                {
                    517:                        memset (header, 0, sizeof (header));
                    518:                        Print ("\rDrive decrypted.\r\n");
                    519:                }
                    520:                else
                    521:                {
                    522:                        // Update encrypted area size in volume header
                    523: 
                    524:                        CRYPTO_INFO *headerCryptoInfo = crypto_open();
                    525:                        ReadSectors (header, drive, headerSector, 1);
                    526: 
                    527:                        if (VolumeReadHeader (TRUE, (char *) header, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0)
                    528:                        {
                    529:                                DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
                    530: 
                    531:                                byte *sizeField = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
                    532:                                uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    533: 
                    534:                                for (int i = 7; i >= 0; --i)
                    535:                                {
                    536:                                        sizeField[i] = (byte) encryptedAreaLength.LowPart;
                    537:                                        encryptedAreaLength = encryptedAreaLength >> 8;
                    538:                                }
                    539:                                
                    540:                                EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
                    541:                        }
                    542: 
                    543:                        crypto_close (headerCryptoInfo);
                    544:                        Print ("\r\nAborted.\r\n");
                    545:                }
                    546: 
                    547:                WriteSectors (header, drive, headerSector, 1);
                    548:        }
                    549: 
                    550: err:
                    551:        memset (bootArguments, 0, sizeof (*bootArguments));
                    552:        GetKeyboardChar();
                    553: }
                    554: 
                    555: 
                    556: static void RepairMenu ()
                    557: {
                    558:        DriveGeometry bootLoaderDriveGeometry;
                    559:        if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry) != BiosResultSuccess)
                    560:        {
                    561:                GetKeyboardChar();
                    562:                return;
                    563:        }
                    564: 
                    565:        while (true)
                    566:        {
                    567:                InitScreen();
                    568:                Print ("Available "); Print ("Repair Options"); Print (":\r\n");
                    569:                PrintRepeatedChar ('\xC4', 25);
                    570:                Print ("\r\n");
                    571: 
                    572:                enum
                    573:                {
                    574:                        RestoreNone = 0,
                    575:                        DecryptVolume,
                    576:                        RestoreTrueCryptLoader,
                    577:                        RestoreVolumeHeader,
                    578:                        RestoreOriginalSystemLoader
                    579:                };
                    580: 
                    581:                static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" };
                    582: 
                    583:                int optionCount = 1;
                    584:                if (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER)
                    585:                        optionCount = array_capacity (options);
                    586:                else if (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK)
                    587:                        optionCount = array_capacity (options) - 1;
                    588: 
                    589:                int selection = AskSelection (options, optionCount);
                    590:                PrintEndl();
                    591: 
1.1.1.2 ! root      592:                switch (selection)
1.1       root      593:                {
1.1.1.2 ! root      594:                        case RestoreNone:
        !           595:                                return;
        !           596: 
        !           597:                        case DecryptVolume:
        !           598:                                DecryptDrive (BootDrive);
        !           599:                                continue;
        !           600: 
        !           601:                        case RestoreOriginalSystemLoader:
        !           602:                                if (!AskYesNo ("Is the drive decrypted"))
        !           603:                                        continue;
1.1       root      604:                }
                    605: 
                    606:                bool writeConfirmed = false;
                    607:                BiosResult result;
                    608:                byte sectorBuf[TC_LB_SIZE];
                    609: 
                    610:                uint64 sector;
                    611:                sector.HighPart = 0;
                    612:                ChsAddress chs;
                    613: 
                    614:                for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
                    615:                        i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
                    616:                {
                    617:                        sector.LowPart = (selection == RestoreOriginalSystemLoader ? TC_ORIG_BOOT_LOADER_BACKUP_SECTOR : 0) + i;
                    618: 
                    619:                        // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
                    620:                        // Therefore, only CHS addressing can be used.
                    621:                        LbaToChs (bootLoaderDriveGeometry, sector, chs);
                    622: 
                    623:                        result = ReadSectors (sectorBuf, BootLoaderDrive, chs, 1);
                    624:                        if (result != BiosResultSuccess)
                    625:                                goto err;
                    626: 
                    627:                        sector.LowPart = i;
                    628: 
                    629:                        // MBR
                    630:                        if (i == TC_MBR_SECTOR)
                    631:                        {
                    632:                                // Preserve partition table
                    633:                                byte bootSecBuf[TC_LB_SIZE];
                    634: 
                    635:                                result = ReadSectors (bootSecBuf, TC_FIRST_BIOS_DRIVE, sector, 1);
                    636:                                if (result != BiosResultSuccess)
                    637:                                        goto err;
                    638: 
                    639:                                memcpy (sectorBuf + TC_MAX_MBR_BOOT_CODE_SIZE,
                    640:                                        bootSecBuf + TC_MAX_MBR_BOOT_CODE_SIZE,
                    641:                                        sizeof (bootSecBuf) - TC_MAX_MBR_BOOT_CODE_SIZE);
                    642: 
                    643:                                // Clear rescue disk flags
                    644:                                if (selection == RestoreTrueCryptLoader)
                    645:                                        sectorBuf[TC_BOOT_SECTOR_CONFIG_OFFSET] &= ~(TC_BOOT_CFG_FLAG_RESCUE_DISK | TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER);
                    646:                        }
                    647: 
                    648:                        // Volume header
                    649:                        if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
                    650:                        {
                    651:                                if (selection == RestoreTrueCryptLoader)
                    652:                                        continue;
                    653: 
                    654:                                if (selection == RestoreVolumeHeader)
                    655:                                {
                    656:                                        while (true)
                    657:                                        {
                    658:                                                Password password;
                    659:                                                byte exitKey = AskPassword (password);
                    660: 
                    661:                                                if (exitKey != TC_BIOS_KEY_ENTER)
                    662:                                                        goto abort;
                    663: 
                    664:                                                CRYPTO_INFO *cryptoInfo;
                    665: 
                    666:                                                // Restore volume header only if the current one cannot be used
                    667:                                                if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo))
                    668:                                                {
                    669:                                                        Print ("Original header preserved.\r\n");
                    670:                                                        crypto_close (cryptoInfo);
                    671:                                                        goto err;
                    672:                                                }
                    673: 
                    674:                                                if (VolumeReadHeader (TRUE, (char *) sectorBuf, &password, &cryptoInfo, nullptr) == 0)
                    675:                                                {
                    676:                                                        crypto_close (cryptoInfo);
                    677:                                                        break;
                    678:                                                }
                    679: 
                    680:                                                Print ("Incorrect password or not a TrueCrypt volume.\r\n\r\n");
                    681:                                        }
                    682:                                }
                    683:                        }
                    684: 
                    685:                        if (!writeConfirmed && !AskYesNo ("Modify Drive 0"))
                    686:                                goto abort;
                    687:                        writeConfirmed = true;
                    688: 
                    689:                        if (WriteSectors (sectorBuf, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
                    690:                                goto err;
                    691:                }
                    692: done:
                    693:                switch (selection)
                    694:                {
                    695:                case RestoreTrueCryptLoader:
                    696:                        Print ("TrueCrypt Boot Loader");
                    697:                        break;
                    698: 
                    699:                case RestoreVolumeHeader:
                    700:                        Print ("Header");
                    701:                        break;
                    702: 
                    703:                case RestoreOriginalSystemLoader:
                    704:                        Print ("System loader");
                    705:                        break;
                    706:                }
                    707:                Print (" restored.\r\n");
                    708: 
                    709: err:   GetKeyboardChar();
                    710: abort: ;
                    711:        }
                    712: }
                    713: 
                    714: 
                    715: #ifndef DEBUG
                    716: extern "C" void _acrtused () { }  // Required by linker
                    717: #endif
                    718: 
                    719: 
                    720: void main ()
                    721: {
                    722:        __asm mov BootLoaderDrive, dl
                    723:        __asm mov BootSectorFlags, dh
                    724: 
                    725: #ifdef TC_TRACING_ENABLED
                    726:        InitDebugPort();
                    727: #endif
                    728: 
                    729:        BootDrive = BootLoaderDrive;
                    730:        if (BootDrive < TC_FIRST_BIOS_DRIVE)
                    731:                BootDrive = TC_FIRST_BIOS_DRIVE;
                    732: 
                    733:        if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
                    734:        {
                    735:                BootDrive = TC_FIRST_BIOS_DRIVE;
                    736:                if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
                    737:                        BootDriveGeometryValid = TRUE;
                    738:        }
                    739:        else
                    740:                BootDriveGeometryValid = TRUE;
                    741: 
                    742:        while (true)
                    743:        {
                    744:                InitScreen();
                    745:                PrintMainMenu();
                    746: 
                    747:                byte exitKey = BootEncryptedDrive();
                    748:                
                    749:                if (exitKey == TC_MENU_KEY_REPAIR)
                    750:                {
                    751:                        RepairMenu();
                    752:                        continue;
                    753:                }
                    754: 
                    755:                BootMenu();
                    756:        }
                    757: }

unix.superglobalmegacorp.com

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