Windows: Don't allow to encrypt the system drive if it is already encrypted by BitLocker

This commit is contained in:
Mounir IDRASSI 2020-07-02 02:10:26 +02:00
parent ac3cccdd21
commit 9a804654f5
No known key found for this signature in database
GPG Key ID: 02C30AE90FAE4A6F
4 changed files with 117 additions and 0 deletions

View File

@ -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())

View File

@ -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;
}

View File

@ -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

View File

@ -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">