1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 02:58:02 -06:00

Windows: Implement RAM encryption for keys on 64-bit machines using ChaCha12 cipher and t1ha non-cryptographic fast hash (https://github.com/leo-yuriev/t1ha)

This commit is contained in:
Mounir IDRASSI
2019-02-26 01:50:27 +01:00
parent 29b749bdd9
commit cf48b532b4
21 changed files with 2241 additions and 21 deletions

View File

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