VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/BootEncryption.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/BootEncryption.cpp')
-rw-r--r--src/Common/BootEncryption.cpp991
1 files changed, 707 insertions, 284 deletions
diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp
index 4061bde9..af6063e4 100644
--- a/src/Common/BootEncryption.cpp
+++ b/src/Common/BootEncryption.cpp
@@ -275,6 +275,27 @@ bool ZipAdd (zip_t *z, const char* name, const unsigned char* pbData, DWORD cbDa
return true;
}
+static BOOL IsWindowsMBR (const byte *buffer, size_t bufferSize)
+{
+ BOOL bRet = FALSE;
+ byte g_pbMsSignature[4] = {0x33, 0xc0, 0x8e, 0xd0};
+ const char* g_szStr1 = "Invalid partition table";
+ const char* g_szStr2 = "Error loading operating system";
+ const char* g_szStr3 = "Missing operating system";
+
+ if ((0 == memcmp (buffer, g_pbMsSignature, 4)) &&
+ (BufferContainsString (buffer, bufferSize, g_szStr1)
+ || BufferContainsString (buffer, bufferSize, g_szStr2)
+ || BufferContainsString (buffer, bufferSize, g_szStr3)
+ )
+ )
+ {
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
namespace VeraCrypt
{
#if !defined (SETUP)
@@ -646,6 +667,18 @@ namespace VeraCrypt
}
}
+ static void NotifyService (DWORD dwNotifyCmd)
+ {
+ Elevate();
+
+ DWORD result = ElevatedComInstance->NotifyService (dwNotifyCmd);
+ if (result != ERROR_SUCCESS)
+ {
+ SetLastError (result);
+ throw SystemException(SRC_POS);
+ }
+ }
+
static void Release ()
{
if (--ReferenceCount == 0 && ElevatedComInstance)
@@ -679,7 +712,7 @@ namespace VeraCrypt
if (!ElevatedComInstance || ElevatedComInstanceThreadId != GetCurrentThreadId())
{
- CoInitialize (NULL);
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg);
ElevatedComInstanceThreadId = GetCurrentThreadId();
}
@@ -775,8 +808,6 @@ namespace VeraCrypt
if (Elevated)
{
- DWORD bytesRead;
-
Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead);
FilePointerPosition += bytesRead;
return bytesRead;
@@ -1030,7 +1061,7 @@ namespace VeraCrypt
static EfiBoot EfiBootInst;
- BootEncryption::BootEncryption (HWND parent, bool postOOBE)
+ BootEncryption::BootEncryption (HWND parent, bool postOOBE, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext)
: DriveConfigValid (false),
ParentWindow (parent),
RealSystemDriveSizeValid (false),
@@ -1041,7 +1072,10 @@ namespace VeraCrypt
SelectedEncryptionAlgorithmId (0),
SelectedPrfAlgorithmId (0),
VolumeHeaderValid (false),
- PostOOBEMode (postOOBE)
+ PostOOBEMode (postOOBE),
+ SetBootNext (setBootNext),
+ SetBootEntry (setBootEntry),
+ ForceFirstBootEntry (forceFirstBootEntry)
{
HiddenOSCandidatePartition.IsGPT = FALSE;
HiddenOSCandidatePartition.Number = (size_t) -1;
@@ -1114,7 +1148,7 @@ namespace VeraCrypt
if (partition.Info.PartitionNumber != config.SystemPartition.Number)
{
// If there is an extra boot partition, the system partition must be located right behind it
- if (IsOSAtLeast (WIN_7) && config.ExtraBootPartitionPresent)
+ if (config.ExtraBootPartitionPresent)
{
int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart;
Partition bootPartition = partition;
@@ -1242,32 +1276,9 @@ namespace VeraCrypt
finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); });
- // Windows versions preceding Vista can be installed on FAT filesystem which does not
- // support long filenames during boot. Convert the driver path to short form if required.
- wstring driverPath;
- if (startOnBoot && !IsOSAtLeast (WIN_VISTA))
- {
- wchar_t pathBuf[MAX_PATH];
- wchar_t filesystem[128];
-
- wstring path (GetWindowsDirectory());
- path += L"\\drivers\\veracrypt.sys";
-
- if (GetVolumePathName (path.c_str(), pathBuf, ARRAYSIZE (pathBuf))
- && GetVolumeInformation (pathBuf, NULL, 0, NULL, NULL, NULL, filesystem, ARRAYSIZE(filesystem))
- && wmemcmp (filesystem, L"FAT", 3) == 0)
- {
- throw_sys_if (GetShortPathName (path.c_str(), pathBuf, ARRAYSIZE (pathBuf)) == 0);
-
- // Convert absolute path to relative to the Windows directory
- driverPath = pathBuf;
- driverPath = driverPath.substr (driverPath.rfind (L"\\", driverPath.rfind (L"\\", driverPath.rfind (L"\\") - 1) - 1) + 1);
- }
- }
-
throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL,
- driverPath.empty() ? NULL : driverPath.c_str(),
+ NULL,
startOnBoot ? L"Filter" : NULL,
NULL, NULL, NULL, NULL, NULL));
@@ -1627,8 +1638,7 @@ namespace VeraCrypt
{
SystemDriveConfiguration config = GetSystemDriveConfiguration();
- if (IsOSAtLeast (WIN_7)
- && config.Partitions.size() == 2
+ if (config.Partitions.size() == 2
&& config.ExtraBootPartitionPresent
&& config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 164 * BYTES_PER_MB)
{
@@ -1677,29 +1687,28 @@ namespace VeraCrypt
if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0)
ea = AES;
- else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
+ #ifndef WOLFCRYPT_BACKEND
+ else if (_stricmp (request.BootEncryptionAlgorithmName, "Camellia") == 0)
+ ea = CAMELLIA;
+ else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
ea = SERPENT;
else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
ea = TWOFISH;
- else if (_stricmp (request.BootEncryptionAlgorithmName, "Camellia") == 0)
- ea = CAMELLIA;
-#if defined(CIPHER_GOST89)
- else if (_stricmp (request.BootEncryptionAlgorithmName, "GOST89") == 0)
- ea = GOST89;
-#endif
-
+ #endif
if (_stricmp(request.BootPrfAlgorithmName, "SHA-256") == 0)
pkcs5_prf = SHA256;
- else if (_stricmp(request.BootPrfAlgorithmName, "RIPEMD-160") == 0)
- pkcs5_prf = RIPEMD160;
- else if (_stricmp(request.BootPrfAlgorithmName, "SHA-512") == 0)
+ else if (_stricmp(request.BootPrfAlgorithmName, "SHA-512") == 0)
pkcs5_prf = SHA512;
+ #ifndef WOLFCRYPT_BACKEND
+ else if (_stricmp(request.BootPrfAlgorithmName, "BLAKE2s-256") == 0)
+ pkcs5_prf = BLAKE2S;
else if (_stricmp(request.BootPrfAlgorithmName, "Whirlpool") == 0)
pkcs5_prf = WHIRLPOOL;
else if (_stricmp(request.BootPrfAlgorithmName, "Streebog") == 0)
pkcs5_prf = STREEBOG;
+ #endif
else if (strlen(request.BootPrfAlgorithmName) == 0) // case of version < 1.0f
- pkcs5_prf = RIPEMD160;
+ pkcs5_prf = BLAKE2S;
}
catch (...)
{
@@ -1725,8 +1734,8 @@ namespace VeraCrypt
pkcs5_prf = SelectedPrfAlgorithmId;
}
- // Only RIPEMD160 and SHA-256 are supported for MBR boot loader
- if (!bIsGPT && pkcs5_prf != RIPEMD160 && pkcs5_prf != SHA256)
+ // Only BLAKE2s and SHA-256 are supported for MBR boot loader
+ if (!bIsGPT && pkcs5_prf != BLAKE2S && pkcs5_prf != SHA256)
throw ParameterIncorrect (SRC_POS);
int bootSectorId = 0;
@@ -1808,8 +1817,7 @@ namespace VeraCrypt
*(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM);
- if (IsOSAtLeast (WIN_VISTA))
- buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
+ buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
if (rescueDisk && (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION))
buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISABLE_HW_ENCRYPTION;
@@ -2196,12 +2204,11 @@ namespace VeraCrypt
#endif // !SETUP
- NtQuerySystemInformationFn NtQuerySystemInformationPtr = NULL;
EfiBootConf::EfiBootConf() : passwordType (0),
passwordMsg ("Password: "),
passwordPicture ("login.bmp"),
- hashMsg ("(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160 (5) STREEBOG\nHash: "),
+ hashMsg ("(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) BLAKE2S (5) STREEBOG\nHash: "),
hashAlgo (0),
requestHash (0),
pimMsg ("PIM (Leave empty for default): "),
@@ -2318,7 +2325,7 @@ namespace VeraCrypt
passwordType = ReadConfigInteger (configContent, "PasswordType", 0);
passwordMsg = ReadConfigString (configContent, "PasswordMsg", "Password: ", buffer, sizeof (buffer));
passwordPicture = ReadConfigString (configContent, "PasswordPicture", "\\EFI\\VeraCrypt\\login.bmp", buffer, sizeof (buffer));
- //hashMsg = ReadConfigString (configContent, "HashMsg", "(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160 (5) STREEBOG\nHash: ", buffer, sizeof (buffer));
+ //hashMsg = ReadConfigString (configContent, "HashMsg", "(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) BLAKE2S (5) STREEBOG\nHash: ", buffer, sizeof (buffer));
hashAlgo = ReadConfigInteger (configContent, "Hash", 0);
requestHash = ReadConfigInteger (configContent, "HashRqt", 1);
pimMsg = ReadConfigString (configContent, "PimMsg", "PIM: ", buffer, sizeof (buffer));
@@ -2364,6 +2371,35 @@ namespace VeraCrypt
WriteConfigInteger (configFile, configContent, "AuthorizeRetry", authorizeRetry);
WriteConfigInteger (configFile, configContent, "DcsBmlLockFlags", bmlLockFlags);
WriteConfigInteger (configFile, configContent, "DcsBmlDriver", bmlDriverEnabled);
+
+ string fieldValue;
+ if (IsPostExecFileField(actionSuccessValue, fieldValue) && (0 == _stricmp(fieldValue.c_str(), "\\EFI\\Microsoft\\Boot\\bootmgfw.efi")))
+ {
+ // fix wrong configuration file since bootmgfw.efi is now a copy of VeraCrypt and if we don't fix the DcsProp
+ // file, veraCrypt bootloader will call itself
+ // We first check if bootmgfw.efi is original Microsoft one. If yes, we don't do anything, otherwise we set the field to bootmgfw_ms.vc
+ unsigned __int64 loaderSize = 0;
+ bool bModifiedMsBoot = true;
+ EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+
+ if (loaderSize > 32768)
+ {
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", &bootLoaderBuf[0], (DWORD) loaderSize);
+
+ // look for bootmgfw.efi identifiant string
+ const char* g_szMsBootString = "bootmgfw.pdb";
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ bModifiedMsBoot = false;
+ }
+ }
+
+ if (bModifiedMsBoot)
+ actionSuccessValue = "postexec file(EFI\\Microsoft\\Boot\\bootmgfw_ms.vc)";
+ }
+
WriteConfigString (configFile, configContent, "ActionSuccess", actionSuccessValue.c_str());
// Write unmodified values
@@ -2396,12 +2432,62 @@ namespace VeraCrypt
return bRet;
}
+ BOOL EfiBootConf::IsPostExecFileField (const string& fieldValue, string& filePath)
+ {
+ BOOL bRet = FALSE;
+ filePath = "";
+
+ if (!fieldValue.empty() && strlen (fieldValue.c_str()))
+ {
+ string copieValue = fieldValue;
+ std::transform(copieValue.begin(), copieValue.end(), copieValue.begin(), ::tolower);
+
+ if (strstr (copieValue.c_str(), "postexec") && strstr (copieValue.c_str(), "file("))
+ {
+ char c;
+ const char* ptr = strstr (copieValue.c_str(), "file(");
+
+ filePath = "\\";
+ ptr += 5;
+ while ((c = *ptr))
+ {
+ if (c == ')')
+ break;
+ if (c == '/')
+ c = '\\';
+ filePath += c;
+ ptr++;
+ }
+
+ if (c == ')')
+ bRet = TRUE;
+ else
+ filePath = "";
+ }
+ }
+
+ return bRet;
+ }
+
+ BOOL EfiBootConf::IsPostExecFileField (const string& fieldValue, wstring& filePath)
+ {
+ string aPath;
+ BOOL bRet = IsPostExecFileField (fieldValue, aPath);
+ if (bRet)
+ filePath = wstring(aPath.begin(), aPath.end());
+ else
+ filePath = L"";
+
+ return bRet;
+ }
+
static const wchar_t* EfiVarGuid = L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}";
void
- GetVolumeESP(wstring& path)
+ GetVolumeESP(wstring& path, wstring& bootVolumePath)
{
static wstring g_EspPath;
+ static wstring g_BootVolumePath;
static bool g_EspPathInitialized = false;
if (!g_EspPathInitialized)
@@ -2409,30 +2495,41 @@ namespace VeraCrypt
ULONG len;
NTSTATUS res;
WCHAR tempBuf[1024];
+ NtQuerySystemInformationFn NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
memset(tempBuf, 0, sizeof(tempBuf));
// Load NtQuerySystemInformation function point
if (!NtQuerySystemInformationPtr)
{
- NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
- if (!NtQuerySystemInformationPtr)
- throw SystemException (SRC_POS);
+ throw SystemException (SRC_POS);
}
res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
if (res != S_OK)
{
+ /* try to convert the returned NTSTATUS to a WIN32 system error using RtlNtStatusToDosError */
+ RtlNtStatusToDosErrorFn RtlNtStatusToDosErrorPtr = (RtlNtStatusToDosErrorFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "RtlNtStatusToDosError");
+ if (RtlNtStatusToDosErrorPtr)
+ {
+ ULONG win32err = RtlNtStatusToDosErrorPtr (res);
+ if (win32err != ERROR_MR_MID_NOT_FOUND)
+ res = (NTSTATUS) win32err;
+ }
+
SetLastError (res);
throw SystemException (SRC_POS);
}
PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
+
+ g_BootVolumePath = pStr->Buffer;
g_EspPath = L"\\\\?";
g_EspPath += &pStr->Buffer[7];
g_EspPathInitialized = true;
}
path = g_EspPath;
+ bootVolumePath = g_BootVolumePath;
}
std::string ReadESPFile (LPCWSTR szFilePath, bool bSkipUTF8BOM)
@@ -2442,9 +2539,9 @@ namespace VeraCrypt
ByteArray fileContent;
DWORD dwSize = 0, dwOffset = 0;
- std::wstring pathESP;
+ std::wstring pathESP, bootVolumePath;
- GetVolumeESP(pathESP);
+ GetVolumeESP(pathESP, bootVolumePath);
if (szFilePath[0] != L'\\')
pathESP += L"\\";
File f(pathESP + szFilePath, true);
@@ -2473,7 +2570,7 @@ namespace VeraCrypt
ByteArray fileContent;
DWORD dwSize = dwDataLen, dwOffset = 0;
- std::wstring pathESP;
+ std::wstring pathESP, bootVolumePath;
if (bAddUTF8BOM)
{
@@ -2481,7 +2578,7 @@ namespace VeraCrypt
dwOffset = 3;
}
- GetVolumeESP(pathESP);
+ GetVolumeESP(pathESP, bootVolumePath);
if (szFilePath[0] != L'\\')
pathESP += L"\\";
@@ -2500,42 +2597,13 @@ namespace VeraCrypt
ZeroMemory (&sdn, sizeof (sdn));
ZeroMemory (&partInfo, sizeof (partInfo));
m_bMounted = false;
- bBootVolumePathSelected = false;
+ bDeviceInfoValid = false;
}
- void EfiBoot::SelectBootVolumeESP() {
- NTSTATUS res;
- ULONG len;
- memset(tempBuf, 0, sizeof(tempBuf));
-
- // Load NtQuerySystemInformation function point
- if (!NtQuerySystemInformationPtr)
- {
- NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
- if (!NtQuerySystemInformationPtr)
- throw SystemException (SRC_POS);
- }
-
- res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
- if (res != S_OK)
- {
- SetLastError (res);
- throw SystemException (SRC_POS);
- }
-
- PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
- BootVolumePath = pStr->Buffer;
-
- EfiBootPartPath = L"\\\\?";
- EfiBootPartPath += &pStr->Buffer[7];
-
- bBootVolumePathSelected = true;
- }
+ void EfiBoot::PrepareBootPartition(bool bDisableException) {
+
+ GetVolumeESP (EfiBootPartPath, BootVolumePath);
- void EfiBoot::PrepareBootPartition() {
- if (!bBootVolumePathSelected) {
- SelectBootVolumeESP();
- }
std::wstring devicePath = L"\\\\?\\GLOBALROOT";
devicePath += BootVolumePath;
Device dev(devicePath.c_str(), TRUE);
@@ -2546,18 +2614,22 @@ namespace VeraCrypt
}
catch (...)
{
- throw;
+ if (!bDisableException)
+ throw;
}
- bool bSuccess = dev.IoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn))
- && dev.IoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, sizeof(partInfo));
- DWORD dwLastError = GetLastError ();
- dev.Close();
- if (!bSuccess)
+ if (dev.IsOpened())
{
- SetLastError (dwLastError);
- throw SystemException(SRC_POS);
- }
+ bDeviceInfoValid = dev.IoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn))
+ && dev.IoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, sizeof(partInfo));
+ DWORD dwLastError = GetLastError ();
+ dev.Close();
+ if (!bDeviceInfoValid && !bDisableException)
+ {
+ SetLastError (dwLastError);
+ throw SystemException(SRC_POS);
+ }
+ }
}
bool EfiBoot::IsEfiBoot() {
@@ -2615,98 +2687,107 @@ namespace VeraCrypt
}
}
- void EfiBoot::SetStartExec(wstring description, wstring execPath, uint16 statrtOrderNum , wchar_t* type, uint32 attr) {
+ void EfiBoot::SetStartExec(wstring description, wstring execPath, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext, uint16 statrtOrderNum , wchar_t* type, uint32 attr) {
SetPrivilege(SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
// Check EFI
if (!IsEfiBoot()) {
throw ErrorException(L"can not detect EFI environment", SRC_POS);
}
- uint32 varSize = 56;
- varSize += ((uint32) description.length()) * 2 + 2;
- varSize += ((uint32) execPath.length()) * 2 + 2;
- byte *startVar = new byte[varSize];
- byte *pVar = startVar;
-
- // Attributes (1b Active, 1000b - Hidden)
- *(uint32 *)pVar = attr;
- pVar += sizeof(uint32);
-
- // Size Of device path + file path
- *(uint16 *)pVar = (uint16)(50 + execPath.length() * 2 + 2);
- pVar += sizeof(uint16);
-
- // description
- for (uint32 i = 0; i < description.length(); i++) {
- *(uint16 *)pVar = description[i];
+ if (bDeviceInfoValid)
+ {
+ uint32 varSize = 56;
+ varSize += ((uint32) description.length()) * 2 + 2;
+ varSize += ((uint32) execPath.length()) * 2 + 2;
+ byte *startVar = new byte[varSize];
+ byte *pVar = startVar;
+
+ // Attributes (1b Active, 1000b - Hidden)
+ *(uint32 *)pVar = attr;
+ pVar += sizeof(uint32);
+
+ // Size Of device path + file path
+ *(uint16 *)pVar = (uint16)(50 + execPath.length() * 2 + 2);
pVar += sizeof(uint16);
- }
- *(uint16 *)pVar = 0;
- pVar += sizeof(uint16);
- /* EFI_DEVICE_PATH_PROTOCOL (HARDDRIVE_DEVICE_PATH \ FILE_PATH \ END) */
+ // description
+ for (uint32 i = 0; i < description.length(); i++) {
+ *(uint16 *)pVar = description[i];
+ pVar += sizeof(uint16);
+ }
+ *(uint16 *)pVar = 0;
+ pVar += sizeof(uint16);
- // Type
- *(byte *)pVar = 0x04;
- pVar += sizeof(byte);
+ /* EFI_DEVICE_PATH_PROTOCOL (HARDDRIVE_DEVICE_PATH \ FILE_PATH \ END) */
- // SubType
- *(byte *)pVar = 0x01;
- pVar += sizeof(byte);
+ // Type
+ *(byte *)pVar = 0x04;
+ pVar += sizeof(byte);
- // HDD dev path length
- *(uint16 *)pVar = 0x2A; // 42
- pVar += sizeof(uint16);
+ // SubType
+ *(byte *)pVar = 0x01;
+ pVar += sizeof(byte);
+
+ // HDD dev path length
+ *(uint16 *)pVar = 0x2A; // 42
+ pVar += sizeof(uint16);
- // PartitionNumber
- *(uint32 *)pVar = (uint32)partInfo.PartitionNumber;
- pVar += sizeof(uint32);
+ // PartitionNumber
+ *(uint32 *)pVar = (uint32)partInfo.PartitionNumber;
+ pVar += sizeof(uint32);
- // PartitionStart
- *(uint64 *)pVar = partInfo.StartingOffset.QuadPart >> 9;
- pVar += sizeof(uint64);
+ // PartitionStart
+ *(uint64 *)pVar = partInfo.StartingOffset.QuadPart >> 9;
+ pVar += sizeof(uint64);
- // PartitiontSize
- *(uint64 *)pVar = partInfo.PartitionLength.QuadPart >> 9;
- pVar += sizeof(uint64);
+ // PartitiontSize
+ *(uint64 *)pVar = partInfo.PartitionLength.QuadPart >> 9;
+ pVar += sizeof(uint64);
- // GptGuid
- memcpy(pVar, &partInfo.Gpt.PartitionId, 16);
- pVar += 16;
+ // GptGuid
+ memcpy(pVar, &partInfo.Gpt.PartitionId, 16);
+ pVar += 16;
- // MbrType
- *(byte *)pVar = 0x02;
- pVar += sizeof(byte);
+ // MbrType
+ *(byte *)pVar = 0x02;
+ pVar += sizeof(byte);
- // SigType
- *(byte *)pVar = 0x02;
- pVar += sizeof(byte);
+ // SigType
+ *(byte *)pVar = 0x02;
+ pVar += sizeof(byte);
- // Type and sub type 04 04 (file path)
- *(uint16 *)pVar = 0x0404;
- pVar += sizeof(uint16);
+ // Type and sub type 04 04 (file path)
+ *(uint16 *)pVar = 0x0404;
+ pVar += sizeof(uint16);
- // SizeOfFilePath ((CHAR16)FullPath.length + sizeof(EndOfrecord marker) )
- *(uint16 *)pVar = (uint16)(execPath.length() * 2 + 2 + sizeof(uint32));
- pVar += sizeof(uint16);
+ // SizeOfFilePath ((CHAR16)FullPath.length + sizeof(EndOfrecord marker) )
+ *(uint16 *)pVar = (uint16)(execPath.length() * 2 + 2 + sizeof(uint32));
+ pVar += sizeof(uint16);
- // FilePath
- for (uint32 i = 0; i < execPath.length(); i++) {
- *(uint16 *)pVar = execPath[i];
+ // FilePath
+ for (uint32 i = 0; i < execPath.length(); i++) {
+ *(uint16 *)pVar = execPath[i];
+ pVar += sizeof(uint16);
+ }
+ *(uint16 *)pVar = 0;
pVar += sizeof(uint16);
- }
- *(uint16 *)pVar = 0;
- pVar += sizeof(uint16);
- // EndOfrecord
- *(uint32 *)pVar = 0x04ff7f;
- pVar += sizeof(uint32);
+ // EndOfrecord
+ *(uint32 *)pVar = 0x04ff7f;
+ pVar += sizeof(uint32);
- // Set variable
- wchar_t varName[256];
- StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
- SetFirmwareEnvironmentVariable(varName, EfiVarGuid, startVar, varSize);
- delete [] startVar;
+ // Set variable
+ wchar_t varName[256];
+ StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
+
+ // only set value if it doesn't already exist
+ byte* existingVar = new byte[varSize];
+ DWORD existingVarLen = GetFirmwareEnvironmentVariableW (varName, EfiVarGuid, existingVar, varSize);
+ if ((existingVarLen != varSize) || (0 != memcmp (existingVar, startVar, varSize)))
+ SetFirmwareEnvironmentVariable(varName, EfiVarGuid, startVar, varSize);
+ delete [] startVar;
+ delete [] existingVar;
+ }
// Update order
wstring order = L"Order";
@@ -2723,42 +2804,183 @@ namespace VeraCrypt
}
}
- // Create new entry if absent
- if (startOrderNumPos == UINT_MAX) {
- for (uint32 i = startOrderLen / 2; i > 0; --i) {
- startOrder[i] = startOrder[i - 1];
+ if (setBootEntry)
+ {
+ // check if first entry in BootOrder is Windows one
+ bool bFirstEntryIsWindows = false;
+ if (startOrderNumPos != 0)
+ {
+ wchar_t varName[256];
+ StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, startOrder[0]);
+
+ byte* existingVar = new byte[512];
+ DWORD existingVarLen = GetFirmwareEnvironmentVariableW (varName, EfiVarGuid, existingVar, 512);
+ if (existingVarLen > 0)
+ {
+ if (BufferContainsWideString (existingVar, existingVarLen, L"EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ bFirstEntryIsWindows = true;
+ }
+
+ delete [] existingVar;
}
- startOrder[0] = statrtOrderNum;
- startOrderLen += 2;
- startOrderUpdate = true;
- } else if (startOrderNumPos > 0) {
- for (uint32 i = startOrderNumPos; i > 0; --i) {
- startOrder[i] = startOrder[i - 1];
+
+
+ // Create new entry if absent
+ if (startOrderNumPos == UINT_MAX) {
+ if (bDeviceInfoValid)
+ {
+ if (forceFirstBootEntry && bFirstEntryIsWindows)
+ {
+ for (uint32 i = startOrderLen / 2; i > 0; --i) {
+ startOrder[i] = startOrder[i - 1];
+ }
+ startOrder[0] = statrtOrderNum;
+ }
+ else
+ {
+ startOrder[startOrderLen/2] = statrtOrderNum;
+ }
+ startOrderLen += 2;
+ startOrderUpdate = true;
+ }
+ } else if ((startOrderNumPos > 0) && forceFirstBootEntry && bFirstEntryIsWindows) {
+ for (uint32 i = startOrderNumPos; i > 0; --i) {
+ startOrder[i] = startOrder[i - 1];
+ }
+ startOrder[0] = statrtOrderNum;
+ startOrderUpdate = true;
+ }
+
+ if (startOrderUpdate) {
+ SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
}
- startOrder[0] = statrtOrderNum;
- startOrderUpdate = true;
}
- if (startOrderUpdate) {
- SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
+ if (setBootNext)
+ {
+ // set BootNext value
+ wstring next = L"Next";
+ next.insert(0, type == NULL ? L"Boot" : type);
+
+ SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &statrtOrderNum, 2);
+
}
+ }
+
+ bool EfiBoot::CompareFiles (const wchar_t* fileName1, const wchar_t* fileName2)
+ {
+ bool bRet = false;
+ File f1 (fileName1, true);
+ File f2 (fileName2, true);
+
+ if (f1.IsOpened() && f2.IsOpened())
+ {
+ try
+ {
+ DWORD size1, size2;
+ f1.GetFileSize (size1);
+ f2.GetFileSize (size2);
+
+ if (size1 == size2)
+ {
+ // same size, so now we compare content
+ std::vector<byte> file1Buf (8096);
+ std::vector<byte> file2Buf (8096);
+ DWORD remainingBytes = size1, dataToRead;
+
+ while (remainingBytes)
+ {
+ dataToRead = VC_MIN (remainingBytes, (DWORD) file1Buf.size());
+ DWORD f1Bytes = f1.Read (file1Buf.data(), dataToRead);
+ DWORD f2Bytes = f2.Read (file2Buf.data(), dataToRead);
+
+ if ((f1Bytes != f2Bytes) || memcmp (file1Buf.data(), file2Buf.data(), (size_t) f1Bytes))
+ {
+ break;
+ }
+ else
+ {
+ remainingBytes -= f1Bytes;
+ }
+ }
+
+ if (0 == remainingBytes)
+ {
+ // content is the same
+ bRet = true;
+ }
+ }
+ }
+ catch (...) {}
+ }
+
+ f1.Close();
+ f2.Close();
+
+ return bRet;
+ }
+
+ bool EfiBoot::CompareFileData (const wchar_t* fileName, const byte* data, DWORD size)
+ {
+ bool bRet = false;
+
+ File f(fileName, true);
+ if (f.IsOpened ())
+ {
+ try
+ {
+ // check if the file has the same content
+ // if yes, don't perform any write operation to avoid changing its timestamp
+ DWORD existingSize = 0;
- // set BootNext value
- wstring next = L"Next";
- next.insert(0, type == NULL ? L"Boot" : type);
+ f.GetFileSize(existingSize);
+
+ if (existingSize == size)
+ {
+ std::vector<byte> fileBuf (8096);
+ DWORD remainingBytes = size, dataOffset = 0, dataToRead;
+
+ while (remainingBytes)
+ {
+ dataToRead = VC_MIN (remainingBytes, (DWORD) fileBuf.size());
+ dataToRead = f.Read (fileBuf.data(), dataToRead);
+
+ if (memcmp (data + dataOffset, fileBuf.data(), (size_t) dataToRead))
+ {
+ break;
+ }
+ else
+ {
+ dataOffset += dataToRead;
+ remainingBytes -= dataToRead;
+ }
+ }
- SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &statrtOrderNum, 2);
+ if (0 == remainingBytes)
+ {
+ // content is the same
+ bRet = true;
+ }
+ }
+ }
+ catch (...){}
+ }
+
+ f.Close();
+ return bRet;
}
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
wstring path = EfiBootPartPath;
path += name;
- File f(path, false, true);
- f.Write(data, size);
- f.Close();
-
+ if (!CompareFileData (path.c_str(), data, size))
+ {
+ File f(path, false, true);
+ f.Write(data, size);
+ f.Close();
+ }
}
bool EfiBoot::FileExists(const wchar_t* name) {
@@ -2797,7 +3019,10 @@ namespace VeraCrypt
}
else
targetPath = targetName;
- throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
+
+ // if both files are the same, we don't perform copy operation
+ if (!CompareFiles (path.c_str(), targetPath.c_str()))
+ throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
}
BOOL EfiBoot::RenameFile(const wchar_t* name, const wchar_t* nameNew, BOOL bForce) {
@@ -2805,7 +3030,16 @@ namespace VeraCrypt
path += name;
wstring pathNew = EfiBootPartPath;
pathNew += nameNew;
- return MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
+
+ BOOL bRet;
+ if (CompareFiles (path.c_str(), pathNew.c_str()))
+ {
+ // files identical. Delete source file only
+ bRet = DeleteFile (path.c_str());
+ }
+ else
+ bRet = MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
+ return bRet;
}
BOOL EfiBoot::DelFile(const wchar_t* name) {
@@ -2955,20 +3189,69 @@ namespace VeraCrypt
if (bForInstall)
{
+ /* Before updating files, we check first if they already have the expected content. If yes, then we don't perform
+ * any write operation to avoid modifying file timestamps Unnecessarily.
+ */
+ bool bSkipWrite = false;
+ wchar_t wszBuffer [2 * TC_MAX_PATH] = {0};
wstring szPathParam = L"\"";
szPathParam += szInstallPath;
szPathParam += L"\"";
- WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", szPathParam.c_str(), szSetupconfigLocation);
+ if ( (0 < GetPrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", L"", wszBuffer, ARRAYSIZE (wszBuffer), szSetupconfigLocation))
+ && (_wcsicmp (wszBuffer, szInstallPath) == 0)
+ )
+ {
+ bSkipWrite = true;
+ }
+
+ if (!bSkipWrite)
+ WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", szPathParam.c_str(), szSetupconfigLocation);
+
+ bSkipWrite = false;
szPathParam = GetProgramConfigPath (L"SetupComplete.cmd");
- FILE* scriptFile = _wfopen (szPathParam.c_str(), L"w");
+
+ wstring wszExpectedValue = L"\"";
+ wszExpectedValue += szInstallPath;
+ wszExpectedValue += L"\\VeraCrypt.exe\" /PostOOBE";
+
+ FILE* scriptFile = _wfopen (szPathParam.c_str(), L"r");
if (scriptFile)
{
- fwprintf (scriptFile, L"\"%s\\VeraCrypt.exe\" /PostOOBE\n", szInstallPath);
+ long fileSize = _filelength (_fileno (scriptFile));
+ if (fileSize < (2 * TC_MAX_PATH))
+ {
+ fgetws (wszBuffer, ARRAYSIZE (wszBuffer), scriptFile);
+
+ if (wszBuffer[wcslen (wszBuffer) - 1] == L'\n')
+ wszBuffer[wcslen (wszBuffer) - 1] = 0;
+
+ bSkipWrite = (0 == _wcsicmp (wszBuffer, wszExpectedValue.c_str()));
+ }
fclose (scriptFile);
+ }
- WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", szPathParam.c_str(), szSetupconfigLocation);
+ if (!bSkipWrite)
+ {
+ scriptFile = _wfopen (szPathParam.c_str(), L"w");
+ if (scriptFile)
+ {
+ fwprintf (scriptFile, L"%s\n", wszExpectedValue.c_str());
+ fclose (scriptFile);
+ }
+ }
+
+ bSkipWrite = false;
+
+ if ( (0 < GetPrivateProfileStringW (L"SetupConfig", L"PostOOBE", L"", wszBuffer, ARRAYSIZE (wszBuffer), szSetupconfigLocation))
+ && (_wcsicmp (wszBuffer, szPathParam.c_str()) == 0)
+ )
+ {
+ bSkipWrite = true;
}
+
+ if (!bSkipWrite)
+ WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", szPathParam.c_str(), szSetupconfigLocation);
}
else
{
@@ -3063,7 +3346,7 @@ namespace VeraCrypt
if (!DcsInfoImg)
throw ErrorException(L"Out of resource DcsInfo", SRC_POS);
- EfiBootInst.PrepareBootPartition();
+ EfiBootInst.PrepareBootPartition(PostOOBEMode);
try
{
@@ -3076,8 +3359,15 @@ namespace VeraCrypt
if (preserveUserConfig)
{
- bool bModifiedMsBoot = true;
- EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+ bool bModifiedMsBoot = true, bMissingMsBoot = false;;
+ if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+ else
+ bMissingMsBoot = true;
+
+ // restore boot menu entry in case of PostOOBE
+ if (PostOOBEMode)
+ EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi", SetBootEntry, ForceFirstBootEntry, SetBootNext);
if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc"))
{
@@ -3120,37 +3410,40 @@ namespace VeraCrypt
EfiBootConf conf;
if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
{
- string actionValue = conf.actionSuccessValue;
- std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
-
- if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
+ wstring loaderPath;
+ if (EfiBootConf::IsPostExecFileField (conf.actionSuccessValue, loaderPath))
{
- char c;
- const char* ptr = strstr (actionValue.c_str(), "file(");
- ptr += 5;
- wstring loaderPath = L"\\";
- while ((c = *ptr))
+ // check that it is not bootmgfw.efi
+ if ( (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ && (EfiBootInst.FileExists (loaderPath.c_str()))
+ )
{
- if (c == ')' || c == ' ')
- break;
- loaderPath += (wchar_t) c;
- ptr++;
+ // look for bootmgfw.efi identifiant string
+ EfiBootInst.GetFileSize(loaderPath.c_str(), loaderSize);
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(loaderPath.c_str(), &bootLoaderBuf[0], (DWORD) loaderSize);
+
+ // look for bootmgfw.efi identifiant string
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ bFound = true;
+ EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
+ }
}
- bFound = true;
- EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
}
}
- if (!bFound)
+ if (!bFound && !PostOOBEMode)
throw ErrorException ("WINDOWS_EFI_BOOT_LOADER_MISSING", SRC_POS);
}
}
- if (PostOOBEMode)
- {
+ if (PostOOBEMode && EfiBootInst.FileExists (L"\\EFI\\VeraCrypt\\DcsBoot.efi"))
+ {
// check if bootmgfw.efi has been set again to Microsoft version
// if yes, replace it with our bootloader after it was copied to bootmgfw_ms.vc
- if (!bModifiedMsBoot)
+ if (!bModifiedMsBoot || bMissingMsBoot)
EfiBootInst.CopyFile (L"\\EFI\\VeraCrypt\\DcsBoot.efi", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
if (EfiBootInst.FileExists (szStdEfiBootloader))
@@ -3187,7 +3480,7 @@ namespace VeraCrypt
EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsInfo.dcs", DcsInfoImg, sizeDcsInfo);
if (!preserveUserConfig)
EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\PlatformInfo");
- EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi");
+ EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi", SetBootEntry, ForceFirstBootEntry, SetBootNext);
if (EfiBootInst.FileExists (szStdEfiBootloader))
{
@@ -3244,50 +3537,67 @@ namespace VeraCrypt
}
else
{
- byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
- CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
+ try
+ {
+ byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
+ CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
- // Write MBR
- byte mbr[TC_SECTOR_SIZE_BIOS];
+ // Write MBR
+ byte mbr[TC_SECTOR_SIZE_BIOS];
- device.SeekAt (0);
- device.Read (mbr, sizeof (mbr));
+ device.SeekAt (0);
+ device.Read (mbr, sizeof (mbr));
- if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME))
- {
- uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
- if (version != 0)
+ if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME))
{
- 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)
+ uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
+ if (version != 0)
{
- if (pim >= 0)
+ 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)
{
- memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
+ 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);
}
- else
- memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
}
}
- }
- memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
+ // perform actual write only if content is different and either we are not in PostOOBE mode or the MBR contains VeraCrypt/Windows signature.
+ // this last check is done to avoid interfering with multi-boot configuration where MBR belongs to a boot manager like Grub
+ if (memcmp (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE)
+ && (!PostOOBEMode || BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME) || IsWindowsMBR (mbr, sizeof (mbr))))
+ {
+ memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
- device.SeekAt (0);
- device.Write (mbr, sizeof (mbr));
+ device.SeekAt (0);
+ device.Write (mbr, sizeof (mbr));
- byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
- device.SeekAt (0);
- device.Read (mbrVerificationBuf, sizeof (mbr));
+ byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
+ device.SeekAt (0);
+ device.Read (mbrVerificationBuf, sizeof (mbr));
- if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
- throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
+ if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
+ throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
+ }
- // Write boot loader
- device.SeekAt (TC_SECTOR_SIZE_BIOS);
- device.Write (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, sizeof (bootLoaderBuf) - TC_SECTOR_SIZE_BIOS);
+ if (!PostOOBEMode)
+ {
+ // Write boot loader
+ device.SeekAt (TC_SECTOR_SIZE_BIOS);
+ device.Write (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, sizeof (bootLoaderBuf) - TC_SECTOR_SIZE_BIOS);
+ }
+ }
+ catch (...)
+ {
+ if (!PostOOBEMode)
+ throw;
+ }
}
if (!IsAdmin() && IsUacSupported())
@@ -3441,16 +3751,23 @@ namespace VeraCrypt
if (!DcsInfoImg)
throw ParameterIncorrect (SRC_POS);
- char szTmpPath[MAX_PATH + 1], szTmpFilePath[MAX_PATH + 1];
- if (!GetTempPathA (MAX_PATH, szTmpPath))
+ WCHAR szTmpPath[MAX_PATH + 1], szTmpFilePath[MAX_PATH + 1];
+ if (!GetTempPathW (MAX_PATH, szTmpPath))
throw SystemException (SRC_POS);
- if (!GetTempFileNameA (szTmpPath, "_vrd", 0, szTmpFilePath))
+ if (!GetTempFileNameW (szTmpPath, L"_vrd", 0, szTmpFilePath))
throw SystemException (SRC_POS);
- finally_do_arg (char*, szTmpFilePath, { DeleteFileA (finally_arg);});
+ finally_do_arg (WCHAR*, szTmpFilePath, { DeleteFileW (finally_arg);});
int ierr;
- zip_t* z = zip_open (szTmpFilePath, ZIP_CREATE | ZIP_TRUNCATE | ZIP_CHECKCONS, &ierr);
+
+ // convert szTmpFilePath to UTF-8 since this is what zip_open expected
+ char szUtf8Path[2*MAX_PATH + 1];
+ int utf8Len = WideCharToMultiByte (CP_UTF8, 0, szTmpFilePath, -1, szUtf8Path, sizeof (szUtf8Path), NULL, NULL);
+ if (utf8Len <= 0)
+ throw SystemException (SRC_POS);
+
+ zip_t* z = zip_open (szUtf8Path, ZIP_CREATE | ZIP_TRUNCATE | ZIP_CHECKCONS, &ierr);
if (!z)
throw ParameterIncorrect (SRC_POS);
@@ -3542,7 +3859,7 @@ namespace VeraCrypt
z = NULL;
// read the zip data from the temporary file
- FILE* ftmpFile = fopen (szTmpFilePath, "rb");
+ FILE* ftmpFile = _wfopen (szTmpFilePath, L"rb");
if (!ftmpFile)
throw ParameterIncorrect (SRC_POS);
@@ -4045,7 +4362,7 @@ namespace VeraCrypt
// Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
- if (0 != ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, pkcs5, pim, FALSE, NULL, cryptoInfo))
+ if (0 != ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, pkcs5, pim, NULL, cryptoInfo))
throw ParameterIncorrect (SRC_POS);
DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
@@ -4230,24 +4547,27 @@ namespace VeraCrypt
EfiBootConf conf;
if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
{
- string actionValue = conf.actionSuccessValue;
- std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
-
- if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
+ wstring loaderPath;
+ if (EfiBootConf::IsPostExecFileField (conf.actionSuccessValue, loaderPath))
{
- char c;
- const char* ptr = strstr (actionValue.c_str(), "file(");
- ptr += 5;
- wstring loaderPath = L"\\";
- while ((c = *ptr))
+ // check that it is not bootmgfw_ms.vc or bootmgfw.efi
+ if ( (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc"))
+ && (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ )
{
- if (c == ')' || c == ' ')
- break;
- loaderPath += (wchar_t) c;
- ptr++;
- }
+ const char* g_szMsBootString = "bootmgfw.pdb";
+ unsigned __int64 loaderSize = 0;
+ EfiBootInst.GetFileSize(loaderPath.c_str(), loaderSize);
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(loaderPath.c_str(), &bootLoaderBuf[0], (DWORD) loaderSize);
- EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE);
+ // look for bootmgfw.efi identifiant string
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE);
+ }
+ }
}
}
}
@@ -4403,9 +4723,6 @@ namespace VeraCrypt
break;
case DumpFilter:
- if (!IsOSAtLeast (WIN_VISTA))
- return;
-
filter = "veracrypt.sys";
filterReg = "DumpFilters";
SetLastError (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\CrashControl", 0, KEY_READ | KEY_WRITE, &regKey));
@@ -4567,6 +4884,16 @@ namespace VeraCrypt
if (registerService)
{
+ // check if service already exists.
+ // If yes then start it immediatly after reinstalling it
+ bool bAlreadyExists = false;
+ SC_HANDLE service = OpenService (scm, TC_SYSTEM_FAVORITES_SERVICE_NAME, GENERIC_READ);
+ if (service)
+ {
+ bAlreadyExists = true;
+ CloseServiceHandle (service);
+ }
+
try
{
RegisterSystemFavoritesService (FALSE, noFileHandling);
@@ -4577,11 +4904,19 @@ namespace VeraCrypt
{
wchar_t appPath[TC_MAX_PATH];
throw_sys_if (!GetModuleFileName (NULL, appPath, ARRAYSIZE (appPath)));
-
+ /* explicitely specify VeraCrypt.exe as the file to copy and don't rely
+ * on the fact we will be always called by VeraCrypt.exe because it's not
+ * always true.
+ */
+ wchar_t* ptr = wcsrchr (appPath, L'\\');
+ if (ptr)
+ ptr[1] = 0;
+ StringCchCatW (appPath, ARRAYSIZE (appPath), _T(TC_APP_NAME) L".exe");
+
throw_sys_if (!CopyFile (appPath, servicePath.c_str(), FALSE));
}
- SC_HANDLE service = CreateService (scm,
+ service = CreateService (scm,
TC_SYSTEM_FAVORITES_SERVICE_NAME,
_T(TC_APP_NAME) L" System Favorites",
SERVICE_ALL_ACCESS,
@@ -4601,6 +4936,10 @@ namespace VeraCrypt
description.lpDescription = L"Mounts VeraCrypt system favorite volumes.";
ChangeServiceConfig2 (service, SERVICE_CONFIG_DESCRIPTION, &description);
+ // start the service immediatly if it already existed before
+ if (bAlreadyExists)
+ StartService (service, 0, NULL);
+
CloseServiceHandle (service);
try
@@ -4642,6 +4981,30 @@ namespace VeraCrypt
}
}
+ bool BootEncryption::IsSystemFavoritesServiceRunning ()
+ {
+ bool bRet = false;
+ SC_HANDLE scm = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
+ if (scm)
+ {
+ SC_HANDLE service = OpenService(scm, TC_SYSTEM_FAVORITES_SERVICE_NAME, GENERIC_READ);
+ if (service)
+ {
+ SERVICE_STATUS status;
+ if (QueryServiceStatus(service, &status))
+ {
+ bRet = (status.dwCurrentState == SERVICE_RUNNING);
+ }
+
+ CloseServiceHandle(service);
+ }
+
+ CloseServiceHandle (scm);
+ }
+
+ return bRet;
+ }
+
void BootEncryption::UpdateSystemFavoritesService ()
{
SC_HANDLE scm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
@@ -4693,7 +5056,7 @@ namespace VeraCrypt
void BootEncryption::SetServiceConfigurationFlag (uint32 flag, bool state)
{
- DWORD configMap = ReadDriverConfigurationFlags();
+ DWORD configMap = ReadServiceConfigurationFlags();
if (state)
configMap |= flag;
@@ -4785,16 +5148,22 @@ namespace VeraCrypt
#endif
#ifndef SETUP
void BootEncryption::CheckRequirements ()
- {
- if (nCurrentOS == WIN_2000)
- throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS", SRC_POS);
-
+ {
if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1)
throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0", SRC_POS);
+ if (IsARM())
+ throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS", SRC_POS);
+
if (IsNonInstallMode())
throw ErrorException ("FEATURE_REQUIRES_INSTALLATION", SRC_POS);
+ /* check if the system drive is already encrypted by BitLocker */
+ wchar_t windowsDrive = (wchar_t) towupper (GetWindowsDirectory()[0]);
+ BitLockerEncryptionStatus bitLockerStatus = GetBitLockerEncryptionStatus (windowsDrive);
+ if (bitLockerStatus == BL_Status_Protected)
+ throw ErrorException ("SYSENC_BITLOCKER_CONFLICT", SRC_POS);
+
SystemDriveConfiguration config = GetSystemDriveConfiguration ();
if (SystemDriveIsDynamic())
@@ -5029,7 +5398,7 @@ namespace VeraCrypt
PCRYPTO_INFO cryptoInfo = NULL;
- int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, old_pkcs5, old_pim, FALSE, &cryptoInfo, NULL);
+ int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, old_pkcs5, old_pim, &cryptoInfo, NULL);
finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
if (status != 0)
@@ -5286,6 +5655,16 @@ namespace VeraCrypt
if (!rescueIsoImagePath.empty())
CreateRescueIsoImage (true, rescueIsoImagePath);
+
+ // check if Fast Startup is enabled and if yes then offer to disable it
+ BOOL bHibernateEnabled = FALSE, bHiberbootEnabled = FALSE;
+ if (GetHibernateStatus (bHibernateEnabled, bHiberbootEnabled) && bHiberbootEnabled)
+ {
+ if (AskWarnYesNo ("CONFIRM_DISABLE_FAST_STARTUP", ParentWindow) == IDYES)
+ {
+ WriteLocalMachineRegistryDwordValue (L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power", L"HiberbootEnabled", 0);
+ }
+ }
}
bool BootEncryption::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly)
@@ -5316,6 +5695,22 @@ namespace VeraCrypt
throw_sys_if (!WriteLocalMachineRegistryDword (keyPath, valueName, value));
}
+ void BootEncryption::NotifyService (DWORD dwNotifyCmd)
+ {
+ if (!IsAdmin() && IsUacSupported())
+ {
+ Elevator::NotifyService (dwNotifyCmd);
+ return;
+ }
+
+ DWORD dwRet = SendServiceNotification(dwNotifyCmd);
+ if (dwRet != ERROR_SUCCESS)
+ {
+ SetLastError(dwRet);
+ throw SystemException (SRC_POS);
+ }
+ }
+
void BootEncryption::StartDecryption (BOOL discardUnreadableEncryptedSectors)
{
BootEncryptionStatus encStatus = GetStatus();
@@ -5440,4 +5835,32 @@ namespace VeraCrypt
{
return (::RestartComputer(bShutdown) != FALSE);
}
+
+ bool BootEncryption::IsUsingUnsupportedAlgorithm(LONG driverVersion)
+ {
+ bool bRet = false;
+
+ try
+ {
+ if (driverVersion <= 0x125)
+ {
+ // version 1.25 is last version to support RIPEMD160 and GOST89
+ static int GOST89_EA = 5;
+ static int RIPEMD160_PRF = 4;
+
+ VOLUME_PROPERTIES_STRUCT props = {0};
+ GetVolumeProperties(&props);
+
+ //
+ if (props.ea == GOST89_EA || props.pkcs5 == RIPEMD160_PRF)
+ bRet = true;
+ }
+ }
+ catch(...)
+ {
+
+ }
+
+ return bRet;
+ }
}