VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common')
-rw-r--r--src/Common/Apidrvr.h1
-rw-r--r--src/Common/Crypto.c209
-rw-r--r--src/Common/Crypto.h21
-rw-r--r--src/Common/EncryptionThreadPool.c45
-rw-r--r--src/Common/Tcdefs.h9
5 files changed, 279 insertions, 6 deletions
diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h
index 63de40ae..2a6941a1 100644
--- a/src/Common/Apidrvr.h
+++ b/src/Common/Apidrvr.h
@@ -418,5 +418,6 @@ typedef struct
#define VC_DRIVER_CONFIG_ALLOW_WINDOWS_DEFRAG 0x200
#define VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION 0x400
#define VC_DRIVER_CONFIG_ENABLE_CPU_RNG 0x800
+#define VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION 0x1000
#endif /* _WIN32 */
diff --git a/src/Common/Crypto.c b/src/Common/Crypto.c
index 249a4117..94fca8e8 100644
--- a/src/Common/Crypto.c
+++ b/src/Common/Crypto.c
@@ -1220,6 +1220,7 @@ BOOL IsHwEncryptionEnabled ()
#ifndef TC_WINDOWS_BOOT
static BOOL CpuRngDisabled = TRUE;
+static BOOL RamEncryptionEnabled = FALSE;
BOOL IsCpuRngSupported ()
{
@@ -1239,6 +1240,214 @@ BOOL IsCpuRngEnabled ()
return !CpuRngDisabled;
}
+BOOL IsRamEncryptionSupported ()
+{
+#ifdef _WIN64
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+void EnableRamEncryption (BOOL enable)
+{
+ RamEncryptionEnabled = enable;
+}
+
+BOOL IsRamEncryptionEnabled ()
+{
+ return RamEncryptionEnabled;
+}
+
+/* masking for random index to remove bias */
+byte GetRngMask (byte count)
+{
+ if (count >= 128)
+ return 0xFF;
+ if (count >= 64)
+ return 0x7F;
+ if (count >= 32)
+ return 0x3F;
+ if (count >= 16)
+ return 0x1F;
+ if (count >= 8)
+ return 0x0F;
+ if (count >= 4)
+ return 0x07;
+ if (count >= 2)
+ return 0x03;
+ return 1;
+}
+
+byte GetRandomIndex (ChaCha20RngCtx* pCtx, byte elementsCount)
+{
+ byte index = 0;
+ byte mask = GetRngMask (elementsCount);
+
+ while (TRUE)
+ {
+ ChaCha20RngGetBytes (pCtx, &index, 1);
+ index &= mask;
+ if (index < elementsCount)
+ break;
+ }
+
+ return index;
+}
+
+#if defined(_WIN64) && !defined (_UEFI) && defined(TC_WINDOWS_DRIVER)
+/* declaration of variables and functions used for RAM encryption on 64-bit build */
+static byte* pbKeyDerivationArea = NULL;
+static ULONG cbKeyDerivationArea = 0;
+
+static uint64 HashSeedMask = 0;
+static uint64 CipherIVMask = 0;
+#ifdef TC_WINDOWS_DRIVER
+ULONG AllocTag = 'MMCV';
+#endif
+
+BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
+{
+ ChaCha20RngCtx ctx;
+ byte pbSeed[CHACHA20RNG_KEYSZ + CHACHA20RNG_IVSZ];
+#ifdef TC_WINDOWS_DRIVER
+ byte i, tagLength;
+#endif
+
+ rngCallback (pbSeed, sizeof (pbSeed));
+
+ ChaCha20RngInit (&ctx, pbSeed, rngCallback, 0);
+
+#ifdef TC_WINDOWS_DRIVER
+ /* generate random tag length between 1 and 4 */
+ tagLength = GetRandomIndex (&ctx, 4) + 1;
+
+ /* generate random value for tag:
+ * Each ASCII character in the tag must be a value in the range 0x20 (space) to 0x7E (tilde)
+ * So we have 95 possibility
+ */
+ AllocTag = 0;
+ for (i = 0; i < tagLength; i++)
+ {
+ AllocTag = (AllocTag << 8) + (((ULONG) GetRandomIndex (&ctx, 95)) + 0x20);
+ }
+
+#endif
+
+ cbKeyDerivationArea = 1024 * 1024;
+ pbKeyDerivationArea = (byte*) TCalloc(cbKeyDerivationArea);
+ if (!pbKeyDerivationArea)
+ {
+ cbKeyDerivationArea = 2 * PAGE_SIZE;
+ pbKeyDerivationArea = (byte*) TCalloc(cbKeyDerivationArea);
+ }
+
+ if (!pbKeyDerivationArea)
+ {
+ cbKeyDerivationArea = 0;
+ return FALSE;
+ }
+
+ /* fill key derivation area with random bytes */
+ ChaCha20RngGetBytes (&ctx, pbKeyDerivationArea, cbKeyDerivationArea);
+
+ /* generate hash seed mask */
+ ChaCha20RngGetBytes(&ctx, (unsigned char*) &HashSeedMask, sizeof (HashSeedMask));
+
+ /* generate IV mask */
+ ChaCha20RngGetBytes(&ctx, (unsigned char*) &CipherIVMask, sizeof (CipherIVMask));
+
+ FAST_ERASE64 (pbSeed, sizeof (pbSeed));
+ burn (&ctx, sizeof (ctx));
+ burn (&tagLength, 1);
+
+ return TRUE;
+}
+
+void ClearSecurityParameters()
+{
+ if (pbKeyDerivationArea)
+ {
+ FAST_ERASE64 (pbKeyDerivationArea, cbKeyDerivationArea);
+ TCfree (pbKeyDerivationArea);
+ pbKeyDerivationArea =NULL;
+ cbKeyDerivationArea = 0;
+ }
+
+ FAST_ERASE64 (&HashSeedMask, 8);
+ FAST_ERASE64 (&CipherIVMask, 8);
+#ifdef TC_WINDOWS_DRIVER
+ burn (&AllocTag, sizeof (AllocTag));
+#endif
+}
+
+#ifdef TC_WINDOWS_DRIVER
+static void VcProtectMemory (uint64 encID, unsigned char* pbData, size_t cbData, unsigned char* pbData2, size_t cbData2)
+#else
+static 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
+{
+ if (pbKeyDerivationArea)
+ {
+ uint64 hashLow, hashHigh, hashSeed, cipherIV;
+ uint64 pbKey[4];
+ ChaCha256Ctx ctx;
+
+ hashSeed = (((uint64) pbKeyDerivationArea) + encID) ^ HashSeedMask;
+ hashLow = t1ha2_atonce128(&hashHigh, pbKeyDerivationArea, cbKeyDerivationArea, hashSeed);
+
+ /* set the key to the hash result */
+ pbKey[0] = pbKey[2] = hashLow;
+ pbKey[1] = pbKey[3] = hashHigh;
+
+ /* Initialize ChaCha12 cipher */
+ cipherIV = encID ^ CipherIVMask;
+ ChaCha256Init (&ctx, (unsigned char*) pbKey, (unsigned char*) &cipherIV, 12);
+
+ ChaCha256Encrypt (&ctx, pbData, cbData, pbData);
+ ChaCha256Encrypt (&ctx, pbData2, cbData2, pbData2);
+#ifndef TC_WINDOWS_DRIVER
+ ChaCha256Encrypt (&ctx, pbData3, cbData3, pbData3);
+ ChaCha256Encrypt (&ctx, pbData4, cbData4, pbData4);
+#endif
+ FAST_ERASE64 (pbKey, sizeof(pbKey));
+ FAST_ERASE64 (&hashLow, 8);
+ FAST_ERASE64 (&hashHigh, 8);
+ FAST_ERASE64 (&hashSeed, 8);
+ FAST_ERASE64 (&cipherIV, 8);
+ burn (&ctx, sizeof (ctx));
+ }
+}
+
+uint64 VcGetEncryptionID (PCRYPTO_INFO pCryptoInfo)
+{
+ return ((uint64) pCryptoInfo->ks) + ((uint64) pCryptoInfo->ks2)
+#ifndef TC_WINDOWS_DRIVER
+ + ((uint64) pCryptoInfo->master_keydata) + ((uint64) pCryptoInfo->k2)
+#endif
+ ;
+}
+
+void VcProtectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID)
+{
+#ifdef TC_WINDOWS_DRIVER
+ VcProtectMemory (encID, pCryptoInfo->ks, MAX_EXPANDED_KEY, pCryptoInfo->ks2, MAX_EXPANDED_KEY);
+#else
+ VcProtectMemory (encID, pCryptoInfo->ks, MAX_EXPANDED_KEY,
+ pCryptoInfo->ks2, MAX_EXPANDED_KEY,
+ pCryptoInfo->master_keydata, MASTER_KEYDATA_SIZE,
+ pCryptoInfo->k2, MASTER_KEYDATA_SIZE);
+#endif
+}
+
+void VcUnprotectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID)
+{
+ VcProtectKeys (pCryptoInfo, encID);
+}
+#endif
#endif
diff --git a/src/Common/Crypto.h b/src/Common/Crypto.h
index 6c2befb1..0951b20b 100644
--- a/src/Common/Crypto.h
+++ b/src/Common/Crypto.h
@@ -208,6 +208,10 @@ typedef struct
# include "GostCipher.h"
# include "kuznyechik.h"
# include "Camellia.h"
+# include "chachaRng.h"
+# ifdef _WIN64
+# include "t1ha.h"
+# endif
#else
# include "CamelliaSmall.h"
#endif
@@ -381,6 +385,19 @@ void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
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);
+#if defined(_WIN64) && !defined (_UEFI) && defined(TC_WINDOWS_DRIVER)
+BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback);
+void ClearSecurityParameters();
+uint64 VcGetEncryptionID (PCRYPTO_INFO pCryptoInfo);
+void VcProtectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID);
+void VcUnprotectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID);
+void EncryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci);
+void DecryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci);
+#else
+#define EncryptDataUnitsCurrentThreadEx EncryptDataUnitsCurrentThread
+#define DecryptDataUnitsCurrentThreadEx DecryptDataUnitsCurrentThread
+#endif
+
BOOL IsAesHwCpuSupported ();
void EnableHwEncryption (BOOL enable);
BOOL IsHwEncryptionEnabled ();
@@ -389,6 +406,10 @@ BOOL IsCpuRngSupported ();
void EnableCpuRng (BOOL enable);
BOOL IsCpuRngEnabled ();
+BOOL IsRamEncryptionSupported ();
+void EnableRamEncryption (BOOL enable);
+BOOL IsRamEncryptionEnabled ();
+
#ifdef __cplusplus
}
#endif
diff --git a/src/Common/EncryptionThreadPool.c b/src/Common/EncryptionThreadPool.c
index 618e8474..fdf1101c 100644
--- a/src/Common/EncryptionThreadPool.c
+++ b/src/Common/EncryptionThreadPool.c
@@ -111,6 +111,43 @@ static TC_MUTEX DequeueMutex;
static TC_EVENT WorkItemReadyEvent;
static TC_EVENT WorkItemCompletedEvent;
+#if defined(_WIN64) && defined(TC_WINDOWS_DRIVER)
+void EncryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci)
+{
+ if (IsRamEncryptionEnabled())
+ {
+ CRYPTO_INFO tmpCI;
+ memcpy (&tmpCI, ci, sizeof (CRYPTO_INFO));
+ VcUnprotectKeys (&tmpCI, VcGetEncryptionID (ci));
+
+ EncryptDataUnitsCurrentThread (buf, structUnitNo, nbrUnits, &tmpCI);
+
+ burn (&tmpCI, sizeof(CRYPTO_INFO));
+ }
+ else
+ EncryptDataUnitsCurrentThread (buf, structUnitNo, nbrUnits, ci);
+}
+
+void DecryptDataUnitsCurrentThreadEx (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci)
+{
+ if (IsRamEncryptionEnabled())
+ {
+ CRYPTO_INFO tmpCI;
+ memcpy (&tmpCI, ci, sizeof (CRYPTO_INFO));
+ VcUnprotectKeys (&tmpCI, VcGetEncryptionID (ci));
+
+ DecryptDataUnitsCurrentThread (buf, structUnitNo, nbrUnits, &tmpCI);
+
+ burn (&tmpCI, sizeof(CRYPTO_INFO));
+ }
+ else
+ DecryptDataUnitsCurrentThread (buf, structUnitNo, nbrUnits, ci);
+}
+
+#else
+#define EncryptDataUnitsCurrentThreadEx EncryptDataUnitsCurrentThread
+#define DecryptDataUnitsCurrentThreadEx DecryptDataUnitsCurrentThread
+#endif
static WorkItemState GetWorkItemState (EncryptionThreadPoolWorkItem *workItem)
{
@@ -152,11 +189,11 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
switch (workItem->Type)
{
case DecryptDataUnitsWork:
- DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
+ DecryptDataUnitsCurrentThreadEx (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
break;
case EncryptDataUnitsWork:
- EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
+ EncryptDataUnitsCurrentThreadEx (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
break;
case DeriveKeyWork:
@@ -414,11 +451,11 @@ void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data,
switch (type)
{
case DecryptDataUnitsWork:
- DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo);
+ DecryptDataUnitsCurrentThreadEx (data, startUnitNo, unitCount, cryptoInfo);
break;
case EncryptDataUnitsWork:
- EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo);
+ EncryptDataUnitsCurrentThreadEx (data, startUnitNo, unitCount, cryptoInfo);
break;
default:
diff --git a/src/Common/Tcdefs.h b/src/Common/Tcdefs.h
index ed0c94bb..47a4bc54 100644
--- a/src/Common/Tcdefs.h
+++ b/src/Common/Tcdefs.h
@@ -248,9 +248,14 @@ void ThrowFatalException(int line);
/* variables used in the implementation of enhanced protection of NX pool under Windows 8 and later */
extern POOL_TYPE ExDefaultNonPagedPoolType;
extern ULONG ExDefaultMdlProtection;
+#ifdef _WIN64
+extern ULONG AllocTag;
+#else
+#define AllocTag 'MMCV'
+#endif
-#define TCalloc(size) ((void *) ExAllocatePoolWithTag( ExDefaultNonPagedPoolType, size, 'MMCV' ))
-#define TCfree(memblock) ExFreePoolWithTag( memblock, 'MMCV' )
+#define TCalloc(size) ((void *) ExAllocatePoolWithTag( ExDefaultNonPagedPoolType, size, AllocTag ))
+#define TCfree(memblock) ExFreePoolWithTag( memblock, AllocTag )
#define DEVICE_DRIVER