|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.