|
|
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:
1.1.1.4 ! root 257: Print ("Incorrect password.\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:
1.1.1.4 ! root 612: if (AskYesNo ("Decrypt now"))
1.1.1.3 root 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.1.4 ! root 626: break;
1.1 root 627: }
628:
629: bool writeConfirmed = false;
630: BiosResult result;
631:
632: uint64 sector;
633: sector.HighPart = 0;
634: ChsAddress chs;
635:
1.1.1.3 root 636: byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE];
637: AcquireSectorBuffer();
638:
1.1 root 639: for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
640: i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
641: {
642: sector.LowPart = (selection == RestoreOriginalSystemLoader ? TC_ORIG_BOOT_LOADER_BACKUP_SECTOR : 0) + i;
643:
644: // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
645: // Therefore, only CHS addressing can be used.
646: LbaToChs (bootLoaderDriveGeometry, sector, chs);
647: sector.LowPart = i;
648:
649: if (i == TC_MBR_SECTOR)
650: {
1.1.1.3 root 651: // Read current partition table
652: result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1);
1.1 root 653: if (result != BiosResultSuccess)
654: goto err;
655:
1.1.1.3 root 656: memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable));
657: }
658:
659: result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1);
660: if (result != BiosResultSuccess)
661: goto err;
662:
663: if (i == TC_MBR_SECTOR)
664: {
665: // Preserve current partition table
666: memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable));
1.1 root 667:
668: // Clear rescue disk flags
669: if (selection == RestoreTrueCryptLoader)
1.1.1.3 root 670: SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] &= ~(TC_BOOT_CFG_FLAG_RESCUE_DISK | TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER);
1.1 root 671: }
672:
673: // Volume header
674: if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
675: {
676: if (selection == RestoreTrueCryptLoader)
677: continue;
678:
679: if (selection == RestoreVolumeHeader)
680: {
681: while (true)
682: {
683: Password password;
684: byte exitKey = AskPassword (password);
685:
686: if (exitKey != TC_BIOS_KEY_ENTER)
687: goto abort;
688:
689: CRYPTO_INFO *cryptoInfo;
690:
1.1.1.3 root 691: CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE);
692: ReleaseSectorBuffer();
693:
1.1 root 694: // Restore volume header only if the current one cannot be used
695: if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo))
696: {
697: Print ("Original header preserved.\r\n");
698: crypto_close (cryptoInfo);
699: goto err;
700: }
701:
1.1.1.3 root 702: AcquireSectorBuffer();
703: CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE);
704:
705: if (VolumeReadHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0)
1.1 root 706: {
707: crypto_close (cryptoInfo);
708: break;
709: }
710:
1.1.1.4 ! root 711: Print ("Incorrect password.\r\n\r\n");
1.1 root 712: }
713: }
714: }
715:
1.1.1.3 root 716: if (!writeConfirmed && !AskYesNo ("Modify drive 0"))
1.1 root 717: goto abort;
718: writeConfirmed = true;
719:
1.1.1.3 root 720: if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
1.1 root 721: goto err;
722: }
723: done:
724: switch (selection)
725: {
726: case RestoreTrueCryptLoader:
727: Print ("TrueCrypt Boot Loader");
728: break;
729:
730: case RestoreVolumeHeader:
731: Print ("Header");
732: break;
733:
734: case RestoreOriginalSystemLoader:
735: Print ("System loader");
736: break;
737: }
738: Print (" restored.\r\n");
739:
740: err: GetKeyboardChar();
1.1.1.3 root 741: abort: ReleaseSectorBuffer();
1.1 root 742: }
743: }
744:
745:
746: #ifndef DEBUG
747: extern "C" void _acrtused () { } // Required by linker
748: #endif
749:
750:
751: void main ()
752: {
753: __asm mov BootLoaderDrive, dl
754: __asm mov BootSectorFlags, dh
755:
1.1.1.3 root 756: #ifdef TC_BOOT_TRACING_ENABLED
1.1 root 757: InitDebugPort();
758: #endif
759:
1.1.1.3 root 760: #ifdef TC_BOOT_STACK_CHECKING_ENABLED
761: InitStackChecker();
762: #endif
763:
1.1 root 764: BootDrive = BootLoaderDrive;
765: if (BootDrive < TC_FIRST_BIOS_DRIVE)
766: BootDrive = TC_FIRST_BIOS_DRIVE;
767:
768: if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
769: {
770: BootDrive = TC_FIRST_BIOS_DRIVE;
771: if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
772: BootDriveGeometryValid = TRUE;
773: }
774: else
775: BootDriveGeometryValid = TRUE;
776:
777: while (true)
778: {
779: InitScreen();
780: PrintMainMenu();
781:
782: byte exitKey = BootEncryptedDrive();
783:
784: if (exitKey == TC_MENU_KEY_REPAIR)
785: {
786: RepairMenu();
787: continue;
788: }
789:
790: BootMenu();
791: }
792: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.