diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2020-07-02 02:10:26 +0200 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2020-07-02 02:20:58 +0200 |
commit | 9a804654f5e8588f039407aeaaaf24fd9f0062e5 (patch) | |
tree | 22773e2465c688f4e17e198c08b6f1b62aedabaa /src/Common | |
parent | ac3cccdd2156403d66b32ef5ab35017caff43209 (diff) | |
download | VeraCrypt-9a804654f5e8588f039407aeaaaf24fd9f0062e5.tar.gz VeraCrypt-9a804654f5e8588f039407aeaaaf24fd9f0062e5.zip |
Windows: Don't allow to encrypt the system drive if it is already encrypted by BitLocker
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/BootEncryption.cpp | 6 | ||||
-rw-r--r-- | src/Common/Dlgcode.c | 102 | ||||
-rw-r--r-- | src/Common/Dlgcode.h | 8 | ||||
-rw-r--r-- | src/Common/Language.xml | 1 |
4 files changed, 117 insertions, 0 deletions
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 @@ <entry lang="en" key="IDC_DISABLE_MOUNT_MANAGER">Only create virtual device without mounting on selected drive letter</entry> <entry lang="en" key="LEGACY_PASSWORD_UTF8_TOO_LONG">The entered password is too long: its UTF-8 representation exceeds 64 bytes.</entry> <entry lang="en" key="HIDDEN_CREDS_SAME_AS_OUTER">The Hidden volume can't have the same password, PIM and keyfiles as the Outer volume</entry> + <entry lang="en" key="SYSENC_BITLOCKER_CONFLICT">VeraCrypt does not support encrypting a system drive that is already encrypted by BitLocker.</entry> </localization> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="VeraCrypt"> |