Windows: Generalize RAM encryption for keys to VeraCrypt binaries, especially Format and Expander

This commit is contained in:
Mounir IDRASSI 2019-03-02 10:14:21 +01:00
parent edd1b00126
commit 321715202a
No known key found for this signature in database
GPG Key ID: 02C30AE90FAE4A6F
12 changed files with 187 additions and 6 deletions

View File

@ -1295,7 +1295,7 @@ byte GetRandomIndex (ChaCha20RngCtx* pCtx, byte elementsCount)
return index; return index;
} }
#if defined(_WIN64) && !defined (_UEFI) && defined(TC_WINDOWS_DRIVER) #if defined(_WIN64) && !defined (_UEFI)
/* declaration of variables and functions used for RAM encryption on 64-bit build */ /* declaration of variables and functions used for RAM encryption on 64-bit build */
static byte* pbKeyDerivationArea = NULL; static byte* pbKeyDerivationArea = NULL;
static ULONG cbKeyDerivationArea = 0; static ULONG cbKeyDerivationArea = 0;
@ -1306,15 +1306,19 @@ static uint64 CipherIVMask = 0;
ULONG AllocTag = 'MMCV'; ULONG AllocTag = 'MMCV';
#endif #endif
#if !defined(PAGE_SIZE)
#define PAGE_SIZE 4096
#endif
BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback) BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
{ {
ChaCha20RngCtx ctx; ChaCha20RngCtx ctx;
byte pbSeed[CHACHA20RNG_KEYSZ + CHACHA20RNG_IVSZ]; byte pbSeed[CHACHA20RNG_KEYSZ + CHACHA20RNG_IVSZ];
#ifdef TC_WINDOWS_DRIVER #ifdef TC_WINDOWS_DRIVER
byte i, tagLength; byte i, tagLength;
#endif
Dump ("InitializeSecurityParameters BEGIN\n"); Dump ("InitializeSecurityParameters BEGIN\n");
#endif
rngCallback (pbSeed, sizeof (pbSeed)); rngCallback (pbSeed, sizeof (pbSeed));
@ -1362,9 +1366,11 @@ BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
FAST_ERASE64 (pbSeed, sizeof (pbSeed)); FAST_ERASE64 (pbSeed, sizeof (pbSeed));
burn (&ctx, sizeof (ctx)); burn (&ctx, sizeof (ctx));
#ifdef TC_WINDOWS_DRIVER
burn (&tagLength, 1); burn (&tagLength, 1);
Dump ("InitializeSecurityParameters return=TRUE END\n"); Dump ("InitializeSecurityParameters return=TRUE END\n");
#endif
return TRUE; return TRUE;
} }

View File

@ -385,10 +385,17 @@ void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo);
void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo);
#if defined(_WIN64) && !defined (_UEFI) && defined(TC_WINDOWS_DRIVER) #if defined(_WIN64) && !defined (_UEFI)
BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback); BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback);
void ClearSecurityParameters(); void ClearSecurityParameters();
#ifdef TC_WINDOWS_DRIVER
void VcProtectMemory (uint64 encID, unsigned char* pbData, size_t cbData, unsigned char* pbData2, size_t cbData2); void VcProtectMemory (uint64 encID, unsigned char* pbData, size_t cbData, unsigned char* pbData2, size_t cbData2);
#else
void VcProtectMemory (uint64 encID, unsigned char* pbData, size_t cbData,
unsigned char* pbData2, size_t cbData2,
unsigned char* pbData3, size_t cbData3,
unsigned char* pbData4, size_t cbData4);
#endif
uint64 VcGetEncryptionID (PCRYPTO_INFO pCryptoInfo); uint64 VcGetEncryptionID (PCRYPTO_INFO pCryptoInfo);
void VcProtectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID); void VcProtectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID);
void VcUnprotectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID); void VcUnprotectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID);

View File

@ -60,6 +60,8 @@
#include "Boot/Windows/BootCommon.h" #include "Boot/Windows/BootCommon.h"
#include "Progress.h" #include "Progress.h"
#include "zip.h" #include "zip.h"
#include "rdrand.h"
#include "jitterentropy.h"
#ifdef TCMOUNT #ifdef TCMOUNT
#include "Mount/Mount.h" #include "Mount/Mount.h"
@ -3203,6 +3205,17 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
InitHelpFileName (); InitHelpFileName ();
#ifndef SETUP #ifndef SETUP
#ifdef _WIN64
if (IsOSAtLeast (WIN_7))
{
EnableRamEncryption ((ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? TRUE : FALSE);
if (IsRamEncryptionEnabled())
{
if (!InitializeSecurityParameters(GetAppRandomSeed))
AbortProcess("OUTOFMEMORY");
}
}
#endif
if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit())) if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit()))
{ {
handleWin32Error (NULL, SRC_POS); handleWin32Error (NULL, SRC_POS);
@ -13894,3 +13907,72 @@ BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void
return bRet; return bRet;
} }
#if !defined(SETUP) && defined(_WIN64)
#define RtlGenRandom SystemFunction036
extern "C" BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed)
{
LARGE_INTEGER iSeed;
SYSTEMTIME sysTime;
byte digest[WHIRLPOOL_DIGESTSIZE];
WHIRLPOOL_CTX tctx;
size_t count;
while (cbRandSeed)
{
WHIRLPOOL_init (&tctx);
// we hash current content of digest buffer which is uninitialized the first time
WHIRLPOOL_add (digest, WHIRLPOOL_DIGESTSIZE, &tctx);
// we use various time information as source of entropy
GetSystemTime (&sysTime);
WHIRLPOOL_add ((unsigned char *) &sysTime, sizeof(sysTime), &tctx);
if (QueryPerformanceCounter (&iSeed))
WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
if (QueryPerformanceFrequency (&iSeed))
WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
/* use Windows random generator as entropy source */
if (RtlGenRandom (digest, sizeof (digest)))
WHIRLPOOL_add (digest, sizeof(digest), &tctx);
/* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */
if (0 == jent_entropy_init ())
{
struct rand_data *ec = jent_entropy_collector_alloc (1, 0);
if (ec)
{
ssize_t rndLen = jent_read_entropy (ec, (char*) digest, sizeof (digest));
if (rndLen > 0)
WHIRLPOOL_add (digest, (unsigned int) rndLen, &tctx);
jent_entropy_collector_free (ec);
}
}
// use RDSEED or RDRAND from CPU as source of entropy if enabled
if ( IsCpuRngEnabled() &&
( (HasRDSEED() && RDSEED_getBytes (digest, sizeof (digest)))
|| (HasRDRAND() && RDRAND_getBytes (digest, sizeof (digest)))
))
{
WHIRLPOOL_add (digest, sizeof(digest), &tctx);
}
WHIRLPOOL_finalize (&tctx, digest);
count = VC_MIN (cbRandSeed, sizeof (digest));
// copy digest value to seed buffer
memcpy (pbRandSeed, digest, count);
cbRandSeed -= count;
pbRandSeed += count;
}
FAST_ERASE64 (digest, sizeof (digest));
FAST_ERASE64 (&iSeed.QuadPart, 8);
burn (&sysTime, sizeof(sysTime));
burn (&tctx, sizeof(tctx));
}
#endif

View File

@ -537,6 +537,9 @@ BOOL VerifyModuleSignature (const wchar_t* path);
void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined); void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined);
BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize); BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize);
BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen); BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen);
#ifdef _WIN64
void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -111,7 +111,7 @@ static TC_MUTEX DequeueMutex;
static TC_EVENT WorkItemReadyEvent; static TC_EVENT WorkItemReadyEvent;
static TC_EVENT WorkItemCompletedEvent; static TC_EVENT WorkItemCompletedEvent;
#if defined(_WIN64) && defined(TC_WINDOWS_DRIVER) #if defined(_WIN64)
void EncryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) void EncryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci)
{ {
if (IsRamEncryptionEnabled()) if (IsRamEncryptionEnabled())

View File

@ -171,6 +171,13 @@ int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
return nStatus? nStatus : ERR_OUTOFMEMORY; return nStatus? nStatus : ERR_OUTOFMEMORY;
} }
#ifdef _WIN64
if (IsRamEncryptionEnabled ())
{
VcProtectKeys (cryptoInfo, VcGetEncryptionID (cryptoInfo));
}
#endif
begin_format: begin_format:
if (volParams->bDevice) if (volParams->bDevice)

View File

@ -343,6 +343,9 @@ extern VOID NTAPI KeRestoreExtendedProcessorState (
# define Dump(...) # define Dump(...)
# define DumpMem(...) # define DumpMem(...)
# endif # endif
#elif !defined (TC_WINDOWS_BOOT)
# define Dump(...)
# define DumpMem(...)
#endif #endif
#if !defined (trace_msg) && !defined (TC_WINDOWS_BOOT) #if !defined (trace_msg) && !defined (TC_WINDOWS_BOOT)

View File

@ -720,6 +720,11 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci)
if (!EAInitMode (ci, key2)) if (!EAInitMode (ci, key2))
return FALSE; return FALSE;
#ifdef _WIN64
if (IsRamEncryptionEnabled ())
VcProtectKeys (ci, VcGetEncryptionID (ci));
#endif
// Each data unit will contain the same plaintext // Each data unit will contain the same plaintext
for (i = 0; i < nbrUnits; i++) for (i = 0; i < nbrUnits; i++)
{ {

View File

@ -232,6 +232,9 @@
<ClCompile Include="SerpentFast_simd.cpp" /> <ClCompile Include="SerpentFast_simd.cpp" />
<ClCompile Include="Sha2.c" /> <ClCompile Include="Sha2.c" />
<ClCompile Include="Streebog.c" /> <ClCompile Include="Streebog.c" />
<ClCompile Include="t1ha2.c" />
<ClCompile Include="t1ha2_selfcheck.c" />
<ClCompile Include="t1ha_selfcheck.c" />
<ClCompile Include="Twofish.c" /> <ClCompile Include="Twofish.c" />
<ClCompile Include="Whirlpool.c" /> <ClCompile Include="Whirlpool.c" />
</ItemGroup> </ItemGroup>
@ -258,6 +261,9 @@
<ClInclude Include="SerpentFast_sbox.h" /> <ClInclude Include="SerpentFast_sbox.h" />
<ClInclude Include="Sha2.h" /> <ClInclude Include="Sha2.h" />
<ClInclude Include="Streebog.h" /> <ClInclude Include="Streebog.h" />
<ClInclude Include="t1ha.h" />
<ClInclude Include="t1ha_bits.h" />
<ClInclude Include="t1ha_selfcheck.h" />
<ClInclude Include="Twofish.h" /> <ClInclude Include="Twofish.h" />
<ClInclude Include="Whirlpool.h" /> <ClInclude Include="Whirlpool.h" />
</ItemGroup> </ItemGroup>

View File

@ -72,6 +72,15 @@
<ClCompile Include="jitterentropy-base.c"> <ClCompile Include="jitterentropy-base.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="t1ha_selfcheck.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="t1ha2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="t1ha2_selfcheck.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Aes.h"> <ClInclude Include="Aes.h">
@ -146,6 +155,15 @@
<ClInclude Include="jitterentropy-base-user.h"> <ClInclude Include="jitterentropy-base-user.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="t1ha.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="t1ha_bits.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="t1ha_selfcheck.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="Aes_hw_cpu.asm"> <CustomBuild Include="Aes_hw_cpu.asm">

View File

@ -672,6 +672,13 @@ static int ExpandVolume (HWND hwndDlg, wchar_t *lpszVolume, Password *pVolumePas
goto error; goto error;
} }
#ifdef _WIN64
if (IsRamEncryptionEnabled())
{
VcProtectKeys (cryptoInfo, VcGetEncryptionID (cryptoInfo));
}
#endif
if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
{ {
nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG; nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;

View File

@ -869,6 +869,13 @@ int EncryptPartitionInPlaceResume (HANDLE dev,
if (nStatus != ERR_SUCCESS) if (nStatus != ERR_SUCCESS)
goto closing_seq; goto closing_seq;
#ifdef _WIN64
if (IsRamEncryptionEnabled ())
{
VcProtectKeys (masterCryptoInfo, VcGetEncryptionID (masterCryptoInfo));
VcProtectKeys (headerCryptoInfo, VcGetEncryptionID (headerCryptoInfo));
}
#endif
remainingBytes = masterCryptoInfo->VolumeSize.Value - masterCryptoInfo->EncryptedAreaLength.Value; remainingBytes = masterCryptoInfo->VolumeSize.Value - masterCryptoInfo->EncryptedAreaLength.Value;
@ -1389,6 +1396,13 @@ int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile
if (nStatus != ERR_SUCCESS) if (nStatus != ERR_SUCCESS)
goto closing_seq; goto closing_seq;
#ifdef _WIN64
if (IsRamEncryptionEnabled ())
{
VcProtectKeys (masterCryptoInfo, VcGetEncryptionID (masterCryptoInfo));
VcProtectKeys (headerCryptoInfo, VcGetEncryptionID (headerCryptoInfo));
}
#endif
if (masterCryptoInfo->LegacyVolume) if (masterCryptoInfo->LegacyVolume)
{ {
@ -1784,6 +1798,7 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
DWORD dwError; DWORD dwError;
uint32 headerCrc32; uint32 headerCrc32;
byte *fieldPos; byte *fieldPos;
PCRYPTO_INFO pCryptoInfo = headerCryptoInfo;
header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
@ -1804,8 +1819,23 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
goto closing_seq; goto closing_seq;
} }
#ifdef _WIN64
if (IsRamEncryptionEnabled())
{
pCryptoInfo = crypto_open();
if (!pCryptoInfo)
{
nStatus = ERR_OUTOFMEMORY;
goto closing_seq;
}
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); memcpy (pCryptoInfo, headerCryptoInfo, sizeof (CRYPTO_INFO));
VcUnprotectKeys (pCryptoInfo, VcGetEncryptionID (headerCryptoInfo));
}
#endif
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, pCryptoInfo);
if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241) if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241)
{ {
@ -1828,7 +1858,7 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC; fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC;
mputLong (fieldPos, headerCrc32); mputLong (fieldPos, headerCrc32);
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, pCryptoInfo);
if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0
@ -1843,6 +1873,13 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
dwError = GetLastError(); dwError = GetLastError();
#ifdef _WIN64
if (IsRamEncryptionEnabled() && pCryptoInfo)
{
crypto_close(pCryptoInfo);
}
#endif
burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
TCfree (header); TCfree (header);