From 1396269d573256248bece97e1e291ef0c08e513f Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 20 Apr 2016 00:30:28 +0200 Subject: Windows: Add option to avoid PIM prompt in pre-boot authentication by storing PIM value unencrypted in MBR. --- src/Common/BootEncryption.cpp | 44 ++++++++++++++++++++++++++++++++++++++----- src/Common/BootEncryption.h | 4 ++-- src/Common/Language.xml | 2 ++ src/Common/Volumes.c | 5 +++-- 4 files changed, 46 insertions(+), 9 deletions(-) (limited to 'src/Common') diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp index 07eb9a99..851d7622 100644 --- a/src/Common/BootEncryption.cpp +++ b/src/Common/BootEncryption.cpp @@ -1300,7 +1300,7 @@ namespace VeraCrypt } - void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage) + void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim) { Device device (GetSystemDriveConfiguration().DevicePath); device.CheckOpened (SRC_POS); @@ -1326,6 +1326,15 @@ namespace VeraCrypt memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size()); } + + if (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM) + { + // PIM for pre-boot authentication can be encoded on two bytes since its maximum + // value is 65535 (0xFFFF) + memcpy (mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE); + } + else + memset (mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, 0, TC_BOOT_SECTOR_PIM_VALUE_SIZE); device.SeekAt (0); device.Write (mbr, sizeof (mbr)); @@ -1494,7 +1503,7 @@ namespace VeraCrypt InstallBootLoader (device, preserveUserConfig, hiddenOSCreation); } - void BootEncryption::InstallBootLoader (Device& device, bool preserveUserConfig, bool hiddenOSCreation) + void BootEncryption::InstallBootLoader (Device& device, bool preserveUserConfig, bool hiddenOSCreation, int pim) { byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0}; CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation); @@ -1512,6 +1521,16 @@ namespace VeraCrypt { bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); + + if (bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM) + { + if (pim >= 0) + { + memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE); + } + else + memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, TC_BOOT_SECTOR_PIM_VALUE_SIZE); + } } } @@ -2499,17 +2518,32 @@ namespace VeraCrypt if (headerUpdated) { + bool storedPimUpdateNeeded = false; ReopenBootVolumeHeaderRequest reopenRequest; reopenRequest.VolumePassword = *newPassword; reopenRequest.pkcs5_prf = cryptoInfo->pkcs5; reopenRequest.pim = pim; finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); }); + if (old_pim != pim) + { + try + { + // check if PIM is stored in MBR + byte userConfig; + ReadBootSectorConfig (nullptr, 0, &userConfig); + if (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM) + storedPimUpdateNeeded = true; + } + catch (...) + {} + } + try { - // force update of bootloader if fingerprint doesn't match - if (!CheckBootloaderFingerprint (true)) - InstallBootLoader (device, true); + // force update of bootloader if fingerprint doesn't match or if the stored PIM changed + if (storedPimUpdateNeeded || !CheckBootloaderFingerprint (true)) + InstallBootLoader (device, true, false, pim); } catch (...) {} diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h index 8aad6708..a922d1fa 100644 --- a/src/Common/BootEncryption.h +++ b/src/Common/BootEncryption.h @@ -169,7 +169,7 @@ namespace VeraCrypt void GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties); SystemDriveConfiguration GetSystemDriveConfiguration (); void Install (bool hiddenSystem); - void InstallBootLoader (Device& device, bool preserveUserConfig = false, bool hiddenOSCreation = false); + void InstallBootLoader (Device& device, bool preserveUserConfig = false, bool hiddenOSCreation = false, int pim = -1); void InstallBootLoader (bool preserveUserConfig = false, bool hiddenOSCreation = false); bool CheckBootloaderFingerprint (bool bSilent = false); void InvalidateCachedSysDriveProperties (); @@ -206,7 +206,7 @@ namespace VeraCrypt void WipeHiddenOSCreationConfig (); void WriteBootDriveSector (uint64 offset, byte *data); void WriteBootSectorConfig (const byte newConfig[]); - void WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage); + void WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim); void WriteLocalMachineRegistryDwordValue (wchar_t *keyPath, wchar_t *valueName, DWORD value); protected: diff --git a/src/Common/Language.xml b/src/Common/Language.xml index cebbc92d..f72e1a30 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1394,6 +1394,8 @@ The Volume ID value is invalid No Volume with the specified ID was found on the system Copy Value to Clipboard... + Do not request PIM in the pre-boot authentication screen (PIM value is stored unencrypted on disk) + WARNING: Please keep in mind that if you enable this option, the PIM value will be stored unencrypted on the disk.\n\nAre you sure you want to enable this option? diff --git a/src/Common/Volumes.c b/src/Common/Volumes.c index d69ef753..955c7e48 100644 --- a/src/Common/Volumes.c +++ b/src/Common/Volumes.c @@ -590,6 +590,7 @@ void ComputeBootloaderFingerprint (byte *bootLoaderBuf, unsigned int bootLoaderS { // compute Whirlpool+SHA512 fingerprint of bootloader including MBR // we skip user configuration fields: + // TC_BOOT_SECTOR_PIM_VALUE_OFFSET = 400 // TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET = 402 // => TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE = 4 // TC_BOOT_SECTOR_USER_MESSAGE_OFFSET = 406 @@ -604,8 +605,8 @@ void ComputeBootloaderFingerprint (byte *bootLoaderBuf, unsigned int bootLoaderS WHIRLPOOL_init (&whirlpool); sha512_begin (&sha2); - WHIRLPOOL_add (bootLoaderBuf, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET * 8, &whirlpool); - sha512_hash (bootLoaderBuf, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, &sha2); + WHIRLPOOL_add (bootLoaderBuf, TC_BOOT_SECTOR_PIM_VALUE_OFFSET * 8, &whirlpool); + sha512_hash (bootLoaderBuf, TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &sha2); WHIRLPOOL_add (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)) * 8, &whirlpool); sha512_hash (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)), &sha2); -- cgit v1.2.3