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

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

unix.superglobalmegacorp.com

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