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