--- truecrypt/boot/windows/bootmain.cpp 2018/04/24 16:58:55 1.1.1.6 +++ truecrypt/boot/windows/bootmain.cpp 2018/04/24 17:12:28 1.1.1.13 @@ -1,9 +1,9 @@ /* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + Copyright (c) 2008-2011 TrueCrypt Developers Association. All rights reserved. - Governed by the TrueCrypt License 2.6 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. */ #include "Crc.h" @@ -30,13 +30,15 @@ static void InitScreen () { ClearScreen(); - Print ( + const char *title = #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE " TrueCrypt Boot Loader " #else " TrueCrypt Rescue Disk " #endif - VERSION_STRING " Copyright (C) 2008 TrueCrypt Foundation\r\n"); + VERSION_STRING "\r\n"; + + Print (title); PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE); @@ -213,13 +215,16 @@ static void ExecuteBootSector (byte driv __asm { cli - mov dl, drive + mov dl, drive // Boot drive + mov dh, 0 xor ax, ax + mov si, ax mov ds, ax mov es, ax mov ss, ax - mov sp, 0xffff + mov sp, 0x7c00 sti + jmp cs:addr } } @@ -283,7 +288,7 @@ static bool CheckMemoryRequirements () __asm mov codeSeg, cs if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT) { - PrintError ("BIOS reserved too much memory: ", true, false); + PrintErrorNoEndl ("BIOS reserved too much memory: "); uint16 memFree; __asm @@ -297,16 +302,7 @@ static bool CheckMemoryRequirements () } Print (memFree); - - Print ("\r\nThis is not a bug in TrueCrypt.\r\n" - "- Disable unneeded components (RAID, AHCI) in BIOS setup menu\r\n" - " (invoked by pressing Del or F2 after turning on your computer)\r\n"); -#ifndef TC_WINDOWS_BOOT_AES - Print ("- Use the AES encryption algorithm to reduce memory requirements\r\n"); -#endif -#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - Print ("- Boot from HDD\r\n"); -#endif + PrintEndl(); Print (TC_BOOT_STR_UPGRADE_BIOS); return false; @@ -342,7 +338,8 @@ static bool MountVolume (byte drive, byt if (++incorrectPasswordCount == 4) { #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - Print ("The key data may be damaged. Use 'Repair Options' > 'Restore key data'.\r\n\r\n"); + Print ("If you are sure the password is correct, the key data may be damaged.\r\n" + "If so, use 'Repair Options' > 'Restore key data'.\r\n\r\n"); #else Print ("If you are sure the password is correct, the key data may be damaged. Boot your\r\n" "TrueCrypt Rescue Disk and select 'Repair Options' > 'Restore key data'.\r\n\r\n"); @@ -354,10 +351,13 @@ static bool MountVolume (byte drive, byt bootArguments->BootLoaderVersion = VERSION_NUM; bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo; bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo); - + if (BootCryptoInfo->hiddenVolume) bootArguments->HiddenSystemPartitionStart = PartitionFollowingActive.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; + if (ExtraBootPartitionPresent) + bootArguments->Flags |= TC_BOOT_ARGS_FLAG_EXTRA_BOOT_PARTITION; + TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature); // Setup virtual encrypted partition @@ -386,13 +386,38 @@ static bool MountVolume (byte drive, byt } +static bool GetSystemPartitions (byte drive) +{ + size_t partCount; + + if (!GetActivePartition (drive)) + return false; + + // Find partition following the active one + GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); + + // If there is an extra boot partition, use the partitions following it. + // The real boot partition is determined in BootEncryptedDrive(). + if (ActivePartition.SectorCount.HighPart == 0 && ActivePartition.SectorCount.LowPart <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE / TC_LB_SIZE + && PartitionFollowingActive.Drive != TC_INVALID_BIOS_DRIVE) + { + ExtraBootPartitionPresent = true; + + ActivePartition = PartitionFollowingActive; + GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); + } + + return true; +} + + static byte BootEncryptedDrive () { BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; byte exitKey; BootCryptoInfo = NULL; - if (!GetActiveAndFollowingPartition (BootDrive)) + if (!GetSystemPartitions (BootDrive)) goto err; if (!MountVolume (BootDrive, exitKey, PreventNormalSystemBoot, false)) @@ -407,6 +432,14 @@ static byte BootEncryptedDrive () bootArguments->DecoySystemPartitionStart = ActivePartition.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; } + if (ExtraBootPartitionPresent && !GetActivePartition (BootDrive)) + goto err; + + if (ReadWriteMBR (false, ActivePartition.Drive) != BiosResultSuccess) + goto err; + + bootArguments->BootDriveSignature = *(uint32 *) (SectorBuffer + 0x1b8); + if (!InstallInterruptFilters()) goto err; @@ -468,6 +501,7 @@ static void BootMenu () // NTFS/FAT partitions must have the boot indicator set to be considered bootable. if (!partition.Active && (*(uint32 *) (SectorBuffer + 3) == 0x5346544e // 'NTFS' + || *(uint32 *) (SectorBuffer + 3) == 0x41465845 && SectorBuffer[7] == 'T' // 'exFAT' || *(uint16 *) (SectorBuffer + 54) == 0x4146 && SectorBuffer[56] == 'T' // 'FAT' || *(uint16 *) (SectorBuffer + 82) == 0x4146 && SectorBuffer[84] == 'T')) { @@ -540,7 +574,7 @@ static void BootMenu () #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE -static bool CopyActivePartitionToHiddenVolume (byte drive, byte &exitKey) +static bool CopySystemPartitionToHiddenVolume (byte drive, byte &exitKey) { bool status = false; @@ -555,7 +589,7 @@ static bool CopyActivePartitionToHiddenV if (!CheckMemoryRequirements ()) goto err; - if (!GetActiveAndFollowingPartition (drive)) + if (!GetSystemPartitions (drive)) goto err; if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE) @@ -565,9 +599,11 @@ static bool CopyActivePartitionToHiddenV AcquireSectorBuffer(); if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess - || (uint16) GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc) + || GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc) { - PrintError ("Your BIOS does not support large drives"); + PrintErrorNoEndl ("Your BIOS does not support large drives"); + Print (IsLbaSupported (PartitionFollowingActive.Drive) ? " due to a bug" : "\r\n- Enable LBA in BIOS"); + PrintEndl(); Print (TC_BOOT_STR_UPGRADE_BIOS); ReleaseSectorBuffer(); @@ -582,11 +618,7 @@ static bool CopyActivePartitionToHiddenV sectorsRemaining = EncryptedVirtualPartition.SectorCount; if (!(sectorsRemaining == ActivePartition.SectorCount)) - { - PrintError ("Hidden volume size differs from system partition"); - crypto_close (BootCryptoInfo); - goto err; - } + TC_THROW_FATAL_EXCEPTION; InitScreen(); Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n"); @@ -601,10 +633,14 @@ static bool CopyActivePartitionToHiddenV } if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) - fragmentSectorCount = sectorsRemaining.LowPart; + fragmentSectorCount = (int) sectorsRemaining.LowPart; if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) - break; + { + Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n"); + crypto_close (BootCryptoInfo); + goto err; + } AcquireSectorBuffer(); @@ -621,7 +657,10 @@ static bool CopyActivePartitionToHiddenV ReleaseSectorBuffer(); if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) - break; + { + crypto_close (BootCryptoInfo); + goto err; + } sectorsRemaining = sectorsRemaining - fragmentSectorCount; sectorOffset = sectorOffset + fragmentSectorCount; @@ -701,7 +740,7 @@ static void DecryptDrive (byte drive) break; if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) - fragmentSectorCount = sectorsRemaining.LowPart; + fragmentSectorCount = (int) sectorsRemaining.LowPart; sector = sector - fragmentSectorCount; @@ -909,6 +948,9 @@ static void RepairMenu () { while (true) { + bool validHeaderPresent = false; + uint32 masterKeyScheduleCrc; + Password password; byte exitKey = AskPassword (password); @@ -923,9 +965,9 @@ static void RepairMenu () // Restore volume header only if the current one cannot be used if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true)) { - Print ("Original header preserved.\r\n"); + validHeaderPresent = true; + masterKeyScheduleCrc = GetCrc32 (cryptoInfo->ks, sizeof (cryptoInfo->ks)); crypto_close (cryptoInfo); - goto err; } AcquireSectorBuffer(); @@ -933,6 +975,17 @@ static void RepairMenu () if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0) { + if (validHeaderPresent) + { + if (masterKeyScheduleCrc == GetCrc32 (cryptoInfo->ks, sizeof (cryptoInfo->ks))) + { + Print ("Original header preserved.\r\n"); + goto err; + } + + Print ("WARNING: Drive 0 contains a valid header!\r\n"); + } + crypto_close (cryptoInfo); break; } @@ -994,6 +1047,8 @@ void main () #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE ReadBootSectorUserConfiguration(); +#elif defined (TC_WINDOWS_BOOT_AES) + EnableHwEncryption (!(BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISABLE_HW_ENCRYPTION)); #endif InitVideoMode(); @@ -1005,15 +1060,21 @@ void main () BootDrive = TC_FIRST_BIOS_DRIVE; // Query boot drive geometry - if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess) + if (GetDriveGeometry (BootDrive, BootDriveGeometry) != BiosResultSuccess) { BootDrive = TC_FIRST_BIOS_DRIVE; - if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess) - BootDriveGeometryValid = TRUE; + if (GetDriveGeometry (BootDrive, BootDriveGeometry) != BiosResultSuccess) + { +#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + Print ("- Connect system drive to (SATA) port 1\r\n"); +#endif + GetKeyboardChar(); + } + else + BootDriveGeometryValid = true; } else - BootDriveGeometryValid = TRUE; - + BootDriveGeometryValid = true; #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE @@ -1054,7 +1115,7 @@ void main () if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING) { - if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey)) + if (CopySystemPartitionToHiddenVolume (BootDrive, exitKey)) { BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING; UpdateBootSectorConfiguration (BootLoaderDrive);