From 9a804654f5e8588f039407aeaaaf24fd9f0062e5 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 2 Jul 2020 02:10:26 +0200 Subject: Windows: Don't allow to encrypt the system drive if it is already encrypted by BitLocker --- src/Common/BootEncryption.cpp | 6 +++ src/Common/Dlgcode.c | 102 ++++++++++++++++++++++++++++++++++++++++++ src/Common/Dlgcode.h | 8 ++++ src/Common/Language.xml | 1 + 4 files changed, 117 insertions(+) (limited to 'src') diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp index 0a2afb12..502b4e06 100644 --- a/src/Common/BootEncryption.cpp +++ b/src/Common/BootEncryption.cpp @@ -5176,6 +5176,12 @@ namespace VeraCrypt 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()) diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 813f2b07..bd1f6f84 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -14372,3 +14372,105 @@ void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed) burn (&tctx, sizeof(tctx)); } #endif + +/* + * GetBitLockerEncryptionStatus: retuns the BitLocker encryption status of a given drive. + */ + +typedef enum BitLockerProtectionState +{ + BL_State_FullyDecrypted = 0, + BL_State_FullyEncrypted = 1, + BL_State_EncryptionInProgress = 2, + BL_State_DecryptionInProgress = 3, + BL_State_EncryptionSuspended = 4, + BL_State_DecryptionSuspended = 5, + BL_State_FullyEncryptedWipeInProgress = 6, + BL_State_FullyEncryptedWipeSuspended = 7 +} BitLockerProtectionState; + +typedef HRESULT (WINAPI *SHCreateItemFromParsingNameFn)( + PCWSTR pszPath, + IBindCtx* pbc, + REFIID riid, + void** ppv +); + +typedef HRESULT (WINAPI *PSGetPropertyKeyFromNameFn)( + _In_ PCWSTR pszName, + _Out_ PROPERTYKEY* ppropkey); + + +/* + Code derived from https://stackoverflow.com/questions/23841973/how-to-tell-if-drive-is-bitlocker-encrypted-without-admin-privilege/47192128#47192128 +*/ +BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter) +{ + HRESULT hr; + BitLockerEncryptionStatus blStatus = BL_Status_Unknown; + wchar_t szDllPath[MAX_PATH] = { 0 }; + HMODULE hShell32 = NULL; + + CoInitialize(NULL); + + if (GetSystemDirectory(szDllPath, MAX_PATH)) + StringCchCatW(szDllPath, MAX_PATH, L"\\Shell32.dll"); + else + StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Shell32.dll"); + + hShell32 = LoadLibrary(szDllPath); + if (hShell32) + { + SHCreateItemFromParsingNameFn SHCreateItemFromParsingNamePtr = (SHCreateItemFromParsingNameFn)GetProcAddress(hShell32, "SHCreateItemFromParsingName"); + if (SHCreateItemFromParsingNamePtr) + { + HMODULE hPropsys = NULL; + + if (GetSystemDirectory(szDllPath, MAX_PATH)) + StringCchCatW(szDllPath, MAX_PATH, L"\\Propsys.dll"); + else + StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Propsys.dll"); + + hPropsys = LoadLibrary(szDllPath); + if (hPropsys) + { + PSGetPropertyKeyFromNameFn PSGetPropertyKeyFromNamePtr = (PSGetPropertyKeyFromNameFn)GetProcAddress(hPropsys, "PSGetPropertyKeyFromName"); + if (PSGetPropertyKeyFromNamePtr) + { + WCHAR parsingName[3] = {driveLetter, L':', 0}; + IShellItem2* drive = NULL; + hr = SHCreateItemFromParsingNamePtr(parsingName, NULL, IID_PPV_ARGS(&drive)); + if (SUCCEEDED(hr)) { + PROPERTYKEY pKey; + hr = PSGetPropertyKeyFromNamePtr(L"System.Volume.BitLockerProtection", &pKey); + if (SUCCEEDED(hr)) { + PROPVARIANT prop; + PropVariantInit(&prop); + hr = drive->GetProperty(pKey, &prop); + if (SUCCEEDED(hr)) { + int status = prop.intVal; + if (status == BL_State_FullyEncrypted || status == BL_State_DecryptionInProgress || status == BL_State_DecryptionSuspended) + blStatus = BL_Status_Protected; + else + blStatus = BL_Status_Unprotected; + } + } + } + if (drive) + drive->Release(); + } + + FreeLibrary(hPropsys); + } + } + else + { + blStatus = BL_Status_Unprotected; // before Vista, there was no Bitlocker + } + + FreeLibrary(hShell32); + } + + CoUninitialize(); + return blStatus; +} diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index 29a13624..9e77c0a9 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -242,6 +242,13 @@ typedef struct } OpenVolumeContext; +typedef enum BitLockerEncryptionStatus +{ + BL_Status_Unknown = 0, + BL_Status_Unprotected, + BL_Status_Protected +} BitLockerEncryptionStatus; + #define DEFAULT_VOL_CREATION_WIZARD_MODE WIZARD_MODE_FILE_CONTAINER @@ -548,6 +555,7 @@ BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize); BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen); BOOL EnableProcessProtection(); void SafeOpenURL (LPCWSTR szUrl); +BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter); #ifdef _WIN64 void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed); #endif diff --git a/src/Common/Language.xml b/src/Common/Language.xml index 3c59f762..d071cec4 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1439,6 +1439,7 @@ Only create virtual device without mounting on selected drive letter The entered password is too long: its UTF-8 representation exceeds 64 bytes. The Hidden volume can't have the same password, PIM and keyfiles as the Outer volume + VeraCrypt does not support encrypting a system drive that is already encrypted by BitLocker. -- cgit v1.2.3