|
|
1.1 root 1: /* 1.1.1.8 ! root 2: Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.6 root 4: Governed by the TrueCrypt License 2.6 the full text of which is contained 1.1 root 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.1.6 root 25: #include "BootStrings.h" 1.1 root 26: #include "IntFilter.h" 27: 28: 29: static void InitScreen () 30: { 31: ClearScreen(); 32: 1.1.1.8 ! root 33: const char *title = 1.1.1.5 root 34: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 35: " TrueCrypt Boot Loader " 36: #else 37: " TrueCrypt Rescue Disk " 38: #endif 1.1.1.8 ! root 39: VERSION_STRING; ! 40: ! 41: Print (title); ! 42: PrintRepeatedChar (' ', title[26] ? 8 : 9); ! 43: Print ("Copyright (C) 2008-2009 TrueCrypt Foundation\r\n"); 1.1 root 44: 1.1.1.5 root 45: PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE); 1.1.1.6 root 46: 47: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 48: if (CustomUserMessage[0]) 49: { 50: PrintEndl(); 51: Print (CustomUserMessage); 52: } 53: #endif 54: 1.1 root 55: PrintEndl (2); 56: } 57: 58: 59: static void PrintMainMenu () 60: { 1.1.1.6 root 61: if (PreventBootMenu) 62: return; 63: 1.1 root 64: Print (" Keyboard Controls:\r\n"); 1.1.1.5 root 65: Print (" [Esc] "); 66: 67: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 68: 1.1.1.6 root 69: Print ((BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE 70: ? "Boot Non-Hidden System (Boot Manager)" 1.1.1.5 root 71: : "Skip Authentication (Boot Manager)"); 72: 73: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 74: 75: Print ("Skip Authentication (Boot Manager)"); 76: Print ("\r\n [F8] "); Print ("Repair Options"); 77: 78: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1.1 root 79: 80: PrintEndl (3); 81: } 82: 83: 84: static bool IsMenuKey (byte scanCode) 85: { 1.1.1.5 root 86: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1.1 root 87: return scanCode == TC_MENU_KEY_REPAIR; 1.1.1.5 root 88: #else 89: return false; 90: #endif 1.1 root 91: } 92: 93: 94: static bool AskYesNo (const char *message) 95: { 96: Print (message); 97: Print ("? (y/n): "); 98: while (true) 99: { 100: switch (GetKeyboardChar()) 101: { 102: case 'y': 103: case 'Y': 1.1.1.3 root 104: case 'z': 1.1.1.6 root 105: case 'Z': 106: Print ("y\r\n"); 1.1 root 107: return true; 108: 109: case 'n': 110: case 'N': 1.1.1.6 root 111: Print ("n\r\n"); 1.1 root 112: return false; 113: 114: default: 115: Beep(); 116: } 117: } 118: } 119: 120: 121: static int AskSelection (const char *options[], size_t optionCount) 122: { 123: for (int i = 0; i < optionCount; ++i) 124: { 125: Print ("["); Print (i + 1); Print ("] "); 126: Print (options[i]); 127: PrintEndl(); 128: } 129: Print ("[Esc] Cancel\r\n\r\n"); 130: 131: Print ("To select, press 1-9: "); 132: 133: char str; 134: 135: while (true) 136: { 137: if (GetString (&str, 1) == 0) 138: return 0; 139: 140: if (str >= '1' && str <= optionCount + '0') 141: return str - '0'; 142: 143: Beep(); 144: PrintBackspace(); 145: } 146: } 147: 148: 1.1.1.6 root 149: static byte AskPassword (Password &password) 1.1 root 150: { 151: size_t pos = 0; 152: byte scanCode; 153: byte asciiCode; 154: 1.1.1.5 root 155: Print ("Enter password"); 1.1.1.6 root 156: Print (PreventNormalSystemBoot ? " for hidden system:\r\n" : ": "); 1.1 root 157: 158: while (true) 159: { 160: asciiCode = GetKeyboardChar (&scanCode); 161: 162: switch (scanCode) 163: { 164: case TC_BIOS_KEY_ENTER: 1.1.1.2 root 165: ClearBiosKeystrokeBuffer(); 1.1 root 166: PrintEndl(); 1.1.1.2 root 167: 168: password.Length = pos; 169: return scanCode; 1.1 root 170: 171: case TC_BIOS_KEY_BACKSPACE: 172: if (pos > 0) 173: { 174: if (pos < MAX_PASSWORD) 175: PrintBackspace(); 176: else 1.1.1.6 root 177: PrintCharAtCursor (' '); 1.1 root 178: 179: --pos; 180: } 181: continue; 182: 183: default: 184: if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode)) 185: { 186: burn (password.Text, sizeof (password.Text)); 1.1.1.2 root 187: ClearBiosKeystrokeBuffer(); 188: 1.1 root 189: PrintEndl(); 190: return scanCode; 191: } 192: } 193: 194: if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD) 195: { 196: Beep(); 197: continue; 198: } 199: 200: password.Text[pos++] = asciiCode; 201: if (pos < MAX_PASSWORD) 202: PrintChar ('*'); 203: else 1.1.1.6 root 204: PrintCharAtCursor ('*'); 1.1 root 205: } 206: } 207: 208: 209: static void ExecuteBootSector (byte drive, byte *sectorBuffer) 210: { 211: Print ("Booting...\r\n"); 212: CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE); 1.1.1.3 root 213: 1.1.1.6 root 214: BootStarted = true; 215: 1.1.1.3 root 216: uint32 addr = 0x7c00; 217: __asm 218: { 219: cli 1.1.1.8 ! root 220: mov dl, drive // Boot drive ! 221: mov dh, 0 1.1.1.3 root 222: xor ax, ax 1.1.1.8 ! root 223: mov si, ax 1.1.1.3 root 224: mov ds, ax 225: mov es, ax 226: mov ss, ax 1.1.1.8 ! root 227: mov sp, 0x7c00 1.1.1.3 root 228: sti 1.1.1.8 ! root 229: 1.1.1.3 root 230: jmp cs:addr 231: } 1.1 root 232: } 233: 234: 1.1.1.6 root 235: static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32, bool skipNormal, bool skipHidden) 1.1 root 236: { 1.1.1.6 root 237: int volumeType; 238: bool hiddenVolume; 1.1 root 239: uint64 headerSec; 1.1.1.5 root 240: 1.1.1.3 root 241: AcquireSectorBuffer(); 1.1 root 242: 1.1.1.6 root 243: for (volumeType = 1; volumeType <= 2; ++volumeType) 1.1 root 244: { 1.1.1.6 root 245: hiddenVolume = (volumeType == 2); 1.1.1.5 root 246: 1.1.1.6 root 247: if (hiddenVolume) 248: { 249: if (skipHidden || PartitionFollowingActive.Drive != drive || PartitionFollowingActive.SectorCount <= ActivePartition.SectorCount) 250: continue; 1.1.1.5 root 251: 1.1.1.6 root 252: headerSec = PartitionFollowingActive.StartSector + TC_HIDDEN_VOLUME_HEADER_OFFSET / TC_LB_SIZE; 253: } 254: else 1.1.1.5 root 255: { 1.1.1.6 root 256: if (skipNormal) 257: continue; 258: 259: headerSec.HighPart = 0; 260: headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; 1.1.1.5 root 261: } 262: 1.1.1.6 root 263: if (ReadSectors (SectorBuffer, drive, headerSec, 1) != BiosResultSuccess) 264: continue; 265: 266: if (ReadVolumeHeader (!hiddenVolume, (char *) SectorBuffer, &password, cryptoInfo, nullptr) == ERR_SUCCESS) 1.1.1.5 root 267: { 1.1.1.6 root 268: // Prevent opening a non-system hidden volume 269: if (hiddenVolume && !((*cryptoInfo)->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)) 270: { 271: crypto_close (*cryptoInfo); 272: continue; 273: } 274: 275: if (headerSaltCrc32) 276: *headerSaltCrc32 = GetCrc32 (SectorBuffer, PKCS5_SALT_SIZE); 1.1.1.5 root 277: 1.1.1.6 root 278: break; 279: } 1.1 root 280: } 281: 1.1.1.3 root 282: ReleaseSectorBuffer(); 1.1.1.6 root 283: return volumeType != 3; 1.1 root 284: } 285: 286: 1.1.1.2 root 287: static bool CheckMemoryRequirements () 288: { 289: uint16 codeSeg; 290: __asm mov codeSeg, cs 291: if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT) 292: { 1.1.1.6 root 293: PrintError ("BIOS reserved too much memory: ", true, false); 1.1.1.2 root 294: 295: uint16 memFree; 296: __asm 297: { 298: push es 299: xor ax, ax 300: mov es, ax 301: mov ax, es:[0x413] 302: mov memFree, ax 303: pop es 304: } 305: 1.1.1.6 root 306: Print (memFree); 1.1.1.8 ! root 307: PrintEndl(); 1.1.1.6 root 308: Print (TC_BOOT_STR_UPGRADE_BIOS); 1.1.1.5 root 309: 1.1.1.2 root 310: return false; 311: } 312: 313: return true; 314: } 315: 316: 1.1.1.5 root 317: static bool MountVolume (byte drive, byte &exitKey, bool skipNormal, bool skipHidden) 1.1 root 318: { 319: BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; 1.1.1.3 root 320: int incorrectPasswordCount = 0; 1.1 root 321: 1.1.1.5 root 322: EraseMemory (bootArguments, sizeof (*bootArguments)); 323: 1.1 root 324: // Open volume header 325: while (true) 326: { 1.1.1.6 root 327: exitKey = AskPassword (bootArguments->BootPassword); 1.1 root 328: 329: if (exitKey != TC_BIOS_KEY_ENTER) 330: return false; 331: 1.1.1.5 root 332: if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32, skipNormal, skipHidden)) 1.1 root 333: break; 334: 1.1.1.5 root 335: if (GetShiftFlags() & TC_BIOS_SHIFTMASK_CAPSLOCK) 336: Print ("Warning: Caps Lock is on.\r\n"); 337: 1.1.1.4 root 338: Print ("Incorrect password.\r\n\r\n"); 1.1.1.3 root 339: 1.1.1.6 root 340: if (++incorrectPasswordCount == 4) 1.1.1.3 root 341: { 1.1.1.6 root 342: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 343: Print ("The key data may be damaged. Use 'Repair Options' > 'Restore key data'.\r\n\r\n"); 344: #else 1.1.1.3 root 345: Print ("If you are sure the password is correct, the key data may be damaged. Boot your\r\n" 346: "TrueCrypt Rescue Disk and select 'Repair Options' > 'Restore key data'.\r\n\r\n"); 1.1.1.6 root 347: #endif 1.1.1.3 root 348: } 1.1 root 349: } 350: 351: // Setup boot arguments 1.1.1.5 root 352: bootArguments->BootLoaderVersion = VERSION_NUM; 1.1 root 353: bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo; 354: bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo); 1.1.1.5 root 355: 356: if (BootCryptoInfo->hiddenVolume) 357: bootArguments->HiddenSystemPartitionStart = PartitionFollowingActive.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; 358: 1.1 root 359: TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature); 360: 1.1.1.5 root 361: // Setup virtual encrypted partition 1.1 root 362: if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0) 363: { 364: EncryptedVirtualPartition.Drive = BootDrive; 365: 1.1.1.5 root 366: EncryptedVirtualPartition.StartSector = BootCryptoInfo->EncryptedAreaStart >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; 367: 368: HiddenVolumeStartUnitNo = EncryptedVirtualPartition.StartSector; 369: HiddenVolumeStartSector = PartitionFollowingActive.StartSector; 370: HiddenVolumeStartSector += EncryptedVirtualPartition.StartSector; 371: 372: EncryptedVirtualPartition.SectorCount = BootCryptoInfo->EncryptedAreaLength >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; 373: 374: EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.SectorCount - 1; 375: EncryptedVirtualPartition.EndSector += EncryptedVirtualPartition.StartSector; 1.1 root 376: } 377: else 378: { 379: // Drive not encrypted 1.1.1.5 root 380: EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; 1.1 root 381: } 382: 383: return true; 384: } 385: 386: 387: static byte BootEncryptedDrive () 388: { 1.1.1.5 root 389: BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; 1.1.1.6 root 390: byte exitKey; 391: BootCryptoInfo = NULL; 1.1 root 392: 1.1.1.5 root 393: if (!GetActiveAndFollowingPartition (BootDrive)) 1.1 root 394: goto err; 395: 1.1.1.6 root 396: if (!MountVolume (BootDrive, exitKey, PreventNormalSystemBoot, false)) 1.1 root 397: return exitKey; 398: 1.1.1.2 root 399: if (!CheckMemoryRequirements ()) 400: goto err; 1.1.1.5 root 401: 402: if (BootCryptoInfo->hiddenVolume) 403: { 404: EncryptedVirtualPartition = ActivePartition; 405: bootArguments->DecoySystemPartitionStart = ActivePartition.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; 1.1.1.2 root 406: } 407: 408: if (!InstallInterruptFilters()) 409: goto err; 1.1 root 410: 1.1.1.5 root 411: bootArguments->BootArgumentsCrc32 = GetCrc32 ((byte *) bootArguments, (byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments); 412: 1.1.1.3 root 413: while (true) 1.1 root 414: { 1.1.1.3 root 415: // Execute boot sector of the active partition 1.1.1.5 root 416: if (ReadSectors (SectorBuffer, ActivePartition.Drive, ActivePartition.StartSector, 1) == BiosResultSuccess) 1.1.1.3 root 417: { 1.1.1.6 root 418: if (*(uint16 *) (SectorBuffer + 510) != 0xaa55) 419: { 420: PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); 421: GetKeyboardChar(); 422: } 423: 1.1.1.5 root 424: ExecuteBootSector (ActivePartition.Drive, SectorBuffer); 1.1.1.3 root 425: } 426: 427: GetKeyboardChar(); 1.1 root 428: } 429: 430: err: 1.1.1.3 root 431: if (BootCryptoInfo) 432: { 433: crypto_close (BootCryptoInfo); 434: BootCryptoInfo = NULL; 435: } 436: 1.1.1.5 root 437: EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; 438: EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); 1.1.1.2 root 439: 1.1 root 440: byte scanCode; 441: GetKeyboardChar (&scanCode); 442: return scanCode; 443: } 444: 445: 446: static void BootMenu () 447: { 448: BiosResult result; 449: Partition partitions[16]; 450: Partition bootablePartitions[9]; 451: size_t partitionCount; 452: size_t bootablePartitionCount = 0; 453: 454: for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive) 455: { 1.1.1.5 root 456: if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, nullptr, true) == BiosResultSuccess) 1.1 root 457: { 458: for (size_t i = 0; i < partitionCount; ++i) 459: { 460: const Partition &partition = partitions[i]; 1.1.1.3 root 461: result = ReadSectors (SectorBuffer, drive, partition.StartSector, 1); 1.1 root 462: 1.1.1.3 root 463: if (result == BiosResultSuccess && *(uint16 *) (SectorBuffer + TC_LB_SIZE - 2) == 0xaa55) 1.1 root 464: { 465: // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore, 466: // NTFS/FAT partitions must have the boot indicator set to be considered bootable. 467: if (!partition.Active 1.1.1.3 root 468: && (*(uint32 *) (SectorBuffer + 3) == 0x5346544e // 'NTFS' 1.1.1.8 ! root 469: || *(uint32 *) (SectorBuffer + 3) == 0x41465845 && SectorBuffer[7] == 'T' // 'exFAT' 1.1.1.3 root 470: || *(uint16 *) (SectorBuffer + 54) == 0x4146 && SectorBuffer[56] == 'T' // 'FAT' 471: || *(uint16 *) (SectorBuffer + 82) == 0x4146 && SectorBuffer[84] == 'T')) 1.1 root 472: { 473: continue; 474: } 475: 476: // Bootable sector found 477: if (bootablePartitionCount < array_capacity (bootablePartitions)) 478: bootablePartitions[bootablePartitionCount++] = partition; 479: } 480: } 481: } 482: } 483: 484: if (bootablePartitionCount < 1) 485: { 1.1.1.6 root 486: PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); 1.1 root 487: GetKeyboardChar(); 488: return; 489: } 490: 491: char partChar; 492: while (true) 493: { 494: InitScreen(); 495: Print ("Bootable Partitions:\r\n"); 496: PrintRepeatedChar ('\xC4', 20); 497: Print ("\r\n"); 498: 499: for (size_t i = 0; i < bootablePartitionCount; ++i) 500: { 501: const Partition &partition = bootablePartitions[i]; 502: Print ("["); Print (i + 1); Print ("] "); 503: Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE); 504: Print (", Partition: "); Print (partition.Number + 1); 1.1.1.5 root 505: Print (", Size: "); PrintSectorCountInMB (partition.SectorCount); PrintEndl(); 1.1 root 506: } 507: 508: if (bootablePartitionCount == 1) 509: { 510: // There's only one bootable partition so we'll boot it directly instead of showing boot manager 511: partChar = '1'; 512: } 513: else 514: { 515: Print ("[Esc] Cancel\r\n\r\n"); 516: Print ("Press 1-9 to select partition: "); 517: 518: if (GetString (&partChar, 1) == 0) 519: return; 520: 521: PrintEndl(); 522: 523: if (partChar < '1' || partChar > '0' + bootablePartitionCount) 524: { 525: Beep(); 526: continue; 527: } 528: } 529: 530: const Partition &partition = bootablePartitions[partChar - '0' - 1]; 531: 1.1.1.3 root 532: if (ReadSectors (SectorBuffer, partition.Drive, partition.StartSector, 1) == BiosResultSuccess) 1.1 root 533: { 1.1.1.3 root 534: ExecuteBootSector (partition.Drive, SectorBuffer); 1.1 root 535: } 536: } 537: } 538: 539: 1.1.1.5 root 540: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 541: 542: static bool CopyActivePartitionToHiddenVolume (byte drive, byte &exitKey) 543: { 544: bool status = false; 545: 546: uint64 sectorsRemaining; 547: uint64 sectorOffset; 548: sectorOffset.LowPart = 0; 549: sectorOffset.HighPart = 0; 550: 551: int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS 552: int statCount; 553: 554: if (!CheckMemoryRequirements ()) 555: goto err; 556: 557: if (!GetActiveAndFollowingPartition (drive)) 558: goto err; 559: 560: if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE) 1.1.1.6 root 561: TC_THROW_FATAL_EXCEPTION; 562: 563: // Check if BIOS can read the last sector of the hidden system 564: AcquireSectorBuffer(); 565: 566: if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess 1.1.1.8 ! root 567: || GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc) 1.1.1.5 root 568: { 1.1.1.8 ! root 569: if (!IsLbaSupported (PartitionFollowingActive.Drive)) ! 570: Print ("BIOS: LBA N/A\r\n"); ! 571: 1.1.1.6 root 572: PrintError ("Your BIOS does not support large drives"); 573: Print (TC_BOOT_STR_UPGRADE_BIOS); 574: 575: ReleaseSectorBuffer(); 1.1.1.5 root 576: goto err; 577: } 578: 1.1.1.6 root 579: ReleaseSectorBuffer(); 580: 1.1.1.5 root 581: if (!MountVolume (drive, exitKey, true, false)) 582: return false; 583: 584: sectorsRemaining = EncryptedVirtualPartition.SectorCount; 585: 586: if (!(sectorsRemaining == ActivePartition.SectorCount)) 1.1.1.7 root 587: TC_THROW_FATAL_EXCEPTION; 1.1.1.5 root 588: 589: InitScreen(); 590: Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n"); 591: 592: while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) 593: { 594: if (EscKeyPressed()) 595: { 596: Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n"); 597: if (AskYesNo ("Abort")) 598: break; 599: } 600: 601: if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) 602: fragmentSectorCount = sectorsRemaining.LowPart; 603: 604: if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) 1.1.1.7 root 605: { 606: Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n"); 607: crypto_close (BootCryptoInfo); 608: goto err; 609: } 1.1.1.5 root 610: 611: AcquireSectorBuffer(); 612: 613: for (int i = 0; i < fragmentSectorCount; ++i) 614: { 615: CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); 616: 617: uint64 s = HiddenVolumeStartUnitNo + sectorOffset + i; 618: EncryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); 619: 620: CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); 621: } 622: 623: ReleaseSectorBuffer(); 624: 625: if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) 1.1.1.7 root 626: { 627: crypto_close (BootCryptoInfo); 628: goto err; 629: } 1.1.1.5 root 630: 631: sectorsRemaining = sectorsRemaining - fragmentSectorCount; 632: sectorOffset = sectorOffset + fragmentSectorCount; 633: 634: if (!(statCount++ & 0xf)) 635: { 636: Print ("\rRemaining: "); 637: PrintSectorCountInMB (sectorsRemaining); 638: } 639: } 640: 641: crypto_close (BootCryptoInfo); 642: 643: if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) 644: { 645: status = true; 646: Print ("\rCopying completed."); 647: } 648: 649: PrintEndl (2); 650: goto ret; 651: 652: err: 653: exitKey = TC_BIOS_KEY_ESC; 654: GetKeyboardChar(); 655: 656: ret: 657: EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); 658: return status; 659: } 660: 661: 662: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 663: 664: 1.1 root 665: static void DecryptDrive (byte drive) 666: { 667: byte exitKey; 1.1.1.5 root 668: if (!MountVolume (drive, exitKey, false, true)) 1.1 root 669: return; 670: 1.1.1.5 root 671: BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; 1.1 root 672: 673: bool headerUpdateRequired = false; 674: uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector; 675: uint64 sector = EncryptedVirtualPartition.EndSector + 1; 676: 1.1.1.5 root 677: int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS 1.1 root 678: int statCount; 679: 1.1.1.5 root 680: bool skipBadSectors = false; 681: 1.1.1.6 root 682: Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n" 683: "(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n"); 1.1.1.5 root 684: 685: if (!AskYesNo ("Decrypt now")) 686: { 687: crypto_close (BootCryptoInfo); 688: goto ret; 689: } 690: 691: if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE) 1.1 root 692: { 1.1.1.3 root 693: // Drive already decrypted 1.1 root 694: sectorsRemaining.HighPart = 0; 695: sectorsRemaining.LowPart = 0; 696: } 697: else 698: { 1.1.1.3 root 699: Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n" 700: "WARNING: You can turn off power only after you press Esc.\r\n\r\n"); 1.1 root 701: } 702: 703: while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) 704: { 1.1.1.5 root 705: if (EscKeyPressed()) 706: break; 1.1 root 707: 708: if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) 709: fragmentSectorCount = sectorsRemaining.LowPart; 710: 711: sector = sector - fragmentSectorCount; 712: 713: if (!(statCount++ & 0xf)) 714: { 715: Print ("\rRemaining: "); 1.1.1.5 root 716: PrintSectorCountInMB (sectorsRemaining); 1.1 root 717: } 718: 1.1.1.5 root 719: if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess) 1.1 root 720: { 1.1.1.5 root 721: AcquireSectorBuffer(); 1.1 root 722: 1.1.1.5 root 723: for (int i = 0; i < fragmentSectorCount; ++i) 724: { 725: CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); 1.1 root 726: 1.1.1.5 root 727: uint64 s = sector + i; 728: DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); 1.1 root 729: 1.1.1.5 root 730: CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); 731: } 1.1.1.3 root 732: 1.1.1.5 root 733: ReleaseSectorBuffer(); 734: 735: if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors) 736: goto askBadSectorSkip; 737: } 738: else if (!skipBadSectors) 739: goto askBadSectorSkip; 1.1 root 740: 741: sectorsRemaining = sectorsRemaining - fragmentSectorCount; 742: headerUpdateRequired = true; 1.1.1.5 root 743: continue; 744: 745: askBadSectorSkip: 746: if (!AskYesNo ("Skip all bad sectors")) 747: break; 748: 749: skipBadSectors = true; 750: sector = sector + fragmentSectorCount; 751: fragmentSectorCount = 1; 1.1 root 752: } 753: 754: crypto_close (BootCryptoInfo); 755: 756: if (headerUpdateRequired) 757: { 1.1.1.3 root 758: AcquireSectorBuffer(); 1.1 root 759: uint64 headerSector; 760: headerSector.HighPart = 0; 761: headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; 762: 1.1.1.3 root 763: // Update encrypted area size in volume header 1.1 root 764: 1.1.1.3 root 765: CRYPTO_INFO *headerCryptoInfo = crypto_open(); 1.1.1.5 root 766: while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); 1.1 root 767: 1.1.1.6 root 768: if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0) 1.1.1.3 root 769: { 770: DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); 1.1 root 771: 1.1.1.3 root 772: uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR; 1.1 root 773: 1.1.1.3 root 774: for (int i = 7; i >= 0; --i) 775: { 1.1.1.5 root 776: SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart; 1.1.1.3 root 777: encryptedAreaLength = encryptedAreaLength >> 8; 1.1 root 778: } 779: 1.1.1.5 root 780: uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); 781: 782: for (i = 3; i >= 0; --i) 783: { 784: SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32; 785: headerCrc32 >>= 8; 786: } 787: 1.1.1.3 root 788: EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); 1.1 root 789: } 790: 1.1.1.3 root 791: crypto_close (headerCryptoInfo); 792: 1.1.1.5 root 793: while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); 1.1.1.3 root 794: ReleaseSectorBuffer(); 1.1 root 795: } 796: 1.1.1.3 root 797: if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) 798: Print ("\rDrive decrypted.\r\n"); 799: else 800: Print ("\r\nDecryption deferred.\r\n"); 801: 1.1 root 802: GetKeyboardChar(); 1.1.1.5 root 803: ret: 804: EraseMemory (bootArguments, sizeof (*bootArguments)); 1.1 root 805: } 806: 807: 808: static void RepairMenu () 809: { 810: DriveGeometry bootLoaderDriveGeometry; 1.1.1.6 root 811: 812: if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess) 1.1 root 813: { 1.1.1.6 root 814: // Some BIOSes may fail to get the geometry of an emulated floppy drive 815: bootLoaderDriveGeometry.Cylinders = 80; 816: bootLoaderDriveGeometry.Heads = 2; 817: bootLoaderDriveGeometry.Sectors = 18; 1.1 root 818: } 819: 820: while (true) 821: { 822: InitScreen(); 823: Print ("Available "); Print ("Repair Options"); Print (":\r\n"); 824: PrintRepeatedChar ('\xC4', 25); 1.1.1.5 root 825: PrintEndl(); 1.1 root 826: 827: enum 828: { 829: RestoreNone = 0, 830: DecryptVolume, 831: RestoreTrueCryptLoader, 832: RestoreVolumeHeader, 833: RestoreOriginalSystemLoader 834: }; 835: 836: static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" }; 837: 1.1.1.5 root 838: int selection = AskSelection (options, 839: (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1); 1.1 root 840: 841: PrintEndl(); 842: 1.1.1.2 root 843: switch (selection) 1.1 root 844: { 1.1.1.2 root 845: case RestoreNone: 846: return; 847: 848: case DecryptVolume: 1.1.1.5 root 849: DecryptDrive (BootDrive); 1.1.1.2 root 850: continue; 851: 852: case RestoreOriginalSystemLoader: 1.1.1.6 root 853: if (!AskYesNo ("Is the system partition/drive decrypted")) 1.1.1.3 root 854: { 855: Print ("Please decrypt it first.\r\n"); 856: GetKeyboardChar(); 1.1.1.2 root 857: continue; 1.1.1.3 root 858: } 1.1.1.4 root 859: break; 1.1 root 860: } 861: 862: bool writeConfirmed = false; 863: BiosResult result; 864: 865: uint64 sector; 866: sector.HighPart = 0; 867: ChsAddress chs; 868: 1.1.1.3 root 869: byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE]; 870: AcquireSectorBuffer(); 871: 1.1 root 872: for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR); 873: i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i) 874: { 1.1.1.5 root 875: sector.LowPart = i; 876: 877: if (selection == RestoreOriginalSystemLoader) 878: sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR; 879: else if (selection == RestoreTrueCryptLoader) 880: sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR; 1.1 root 881: 882: // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used. 883: // Therefore, only CHS addressing can be used. 884: LbaToChs (bootLoaderDriveGeometry, sector, chs); 885: sector.LowPart = i; 886: 887: if (i == TC_MBR_SECTOR) 888: { 1.1.1.3 root 889: // Read current partition table 890: result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1); 1.1 root 891: if (result != BiosResultSuccess) 892: goto err; 893: 1.1.1.3 root 894: memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable)); 895: } 896: 897: result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1); 898: if (result != BiosResultSuccess) 899: goto err; 900: 901: if (i == TC_MBR_SECTOR) 902: { 903: // Preserve current partition table 904: memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable)); 1.1 root 905: } 906: 907: // Volume header 908: if (i == TC_BOOT_VOLUME_HEADER_SECTOR) 909: { 910: if (selection == RestoreTrueCryptLoader) 911: continue; 912: 913: if (selection == RestoreVolumeHeader) 914: { 915: while (true) 916: { 917: Password password; 918: byte exitKey = AskPassword (password); 919: 920: if (exitKey != TC_BIOS_KEY_ENTER) 921: goto abort; 922: 923: CRYPTO_INFO *cryptoInfo; 924: 1.1.1.3 root 925: CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE); 926: ReleaseSectorBuffer(); 927: 1.1 root 928: // Restore volume header only if the current one cannot be used 1.1.1.5 root 929: if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true)) 1.1 root 930: { 931: Print ("Original header preserved.\r\n"); 932: crypto_close (cryptoInfo); 933: goto err; 934: } 935: 1.1.1.3 root 936: AcquireSectorBuffer(); 937: CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE); 938: 1.1.1.6 root 939: if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0) 1.1 root 940: { 941: crypto_close (cryptoInfo); 942: break; 943: } 944: 1.1.1.4 root 945: Print ("Incorrect password.\r\n\r\n"); 1.1 root 946: } 947: } 948: } 949: 1.1.1.3 root 950: if (!writeConfirmed && !AskYesNo ("Modify drive 0")) 1.1 root 951: goto abort; 952: writeConfirmed = true; 953: 1.1.1.3 root 954: if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess) 1.1 root 955: goto err; 956: } 957: done: 958: switch (selection) 959: { 960: case RestoreTrueCryptLoader: 961: Print ("TrueCrypt Boot Loader"); 962: break; 963: 964: case RestoreVolumeHeader: 965: Print ("Header"); 966: break; 967: 968: case RestoreOriginalSystemLoader: 969: Print ("System loader"); 970: break; 971: } 972: Print (" restored.\r\n"); 973: 974: err: GetKeyboardChar(); 1.1.1.3 root 975: abort: ReleaseSectorBuffer(); 1.1 root 976: } 977: } 978: 1.1.1.5 root 979: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 980: 1.1 root 981: 982: #ifndef DEBUG 983: extern "C" void _acrtused () { } // Required by linker 984: #endif 985: 986: 987: void main () 988: { 989: __asm mov BootLoaderDrive, dl 990: __asm mov BootSectorFlags, dh 991: 1.1.1.3 root 992: #ifdef TC_BOOT_TRACING_ENABLED 1.1 root 993: InitDebugPort(); 994: #endif 995: 1.1.1.3 root 996: #ifdef TC_BOOT_STACK_CHECKING_ENABLED 997: InitStackChecker(); 998: #endif 999: 1.1.1.6 root 1000: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1001: ReadBootSectorUserConfiguration(); 1002: #endif 1003: 1.1.1.5 root 1004: InitVideoMode(); 1005: InitScreen(); 1006: 1007: // Determine boot drive 1.1 root 1008: BootDrive = BootLoaderDrive; 1009: if (BootDrive < TC_FIRST_BIOS_DRIVE) 1010: BootDrive = TC_FIRST_BIOS_DRIVE; 1011: 1.1.1.5 root 1012: // Query boot drive geometry 1.1 root 1013: if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess) 1014: { 1015: BootDrive = TC_FIRST_BIOS_DRIVE; 1016: if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess) 1017: BootDriveGeometryValid = TRUE; 1018: } 1019: else 1020: BootDriveGeometryValid = TRUE; 1021: 1.1.1.5 root 1022: 1023: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1024: 1025: // Check whether the user is not using the Rescue Disk to create a hidden system 1026: 1027: if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess 1028: && *(uint32 *) (SectorBuffer + 6) == 0x65757254 1029: && *(uint32 *) (SectorBuffer + 10) == 0x70797243 1030: && (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE) 1031: { 1032: PrintError ("It appears you are creating a hidden OS."); 1033: if (AskYesNo ("Is this correct")) 1034: { 1035: Print ("Please remove the Rescue Disk from the drive and restart."); 1036: while (true); 1037: } 1038: } 1039: 1040: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1041: 1042: 1043: // Main menu 1044: 1.1 root 1045: while (true) 1046: { 1.1.1.5 root 1047: byte exitKey; 1.1 root 1048: InitScreen(); 1049: 1.1.1.5 root 1050: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1051: 1052: // Hidden system setup 1053: byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; 1054: 1055: if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE) 1056: { 1.1.1.6 root 1057: PreventNormalSystemBoot = true; 1.1.1.5 root 1058: PrintMainMenu(); 1059: 1060: if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING) 1061: { 1062: if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey)) 1063: { 1.1.1.6 root 1064: BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING; 1.1.1.5 root 1065: UpdateBootSectorConfiguration (BootLoaderDrive); 1066: } 1067: else if (exitKey == TC_BIOS_KEY_ESC) 1068: goto bootMenu; 1069: else 1070: continue; 1071: } 1072: } 1073: else 1074: PrintMainMenu(); 1075: 1076: exitKey = BootEncryptedDrive(); 1077: 1078: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1.1 root 1079: 1.1.1.5 root 1080: PrintMainMenu(); 1081: exitKey = BootEncryptedDrive(); 1082: 1.1 root 1083: if (exitKey == TC_MENU_KEY_REPAIR) 1084: { 1085: RepairMenu(); 1086: continue; 1087: } 1088: 1.1.1.5 root 1089: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE 1090: 1091: bootMenu: 1.1.1.6 root 1092: if (!PreventBootMenu) 1093: BootMenu(); 1.1 root 1094: } 1095: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.