VeraCrypt RAM Encryption aims to protect disk encryption keys stored in volatile memory against certain types of attacks. The primary objectives of this mechanism are:
Here's a summary of how RAM encryption is achieved:
HashSeedMask
and CipherIVMask
, are generated.The mitigation of cold boot attacks is achieved by utilizing a large memory page for key derivation. This ensures that attackers cannot recover the master key since parts of this large memory area would likely be corrupted and irrecoverable after shutdown. Further details on cold boot attacks and mitigation techniques can be found in the referenced papers:
RAM Encryption in VeraCrypt is not compatible with the Windows Hibernate and Fast Startup features. Before activating RAM Encryption, these features will be disabled by VeraCrypt to ensure the security and functionality of the encryption mechanism.
The choice of algorithms was based on a balance between security and performance:
Two core algorithms are fundamental to the RAM encryption process:
Computes a unique ID for the RAM buffer set to be encrypted.
- Input: pCryptoInfo, a CRYPTO_INFO variable to encrypt/decrypt
- Output: A 64-bit integer identifying the pCryptoInfo variable
- Steps:
- Compute the sum of the virtual memory addresses of the fields ks and ks2 of pCryptoInfo: encID = ((uint64) pCryptoInfo->ks) + ((uint64) pCryptoInfo->ks2)
- Return the result
Encrypts the RAM buffer using the unique ID generated by VcGetEncryptionID.
- Input:
- encID, unique ID for memory to be encrypted
- pbData, pointer to the memory to be encrypted
- pbKeyDerivationArea, memory area allocated by the driver at startup
- HashSeedMask and CipherIVMask, two 64-bit random integers from startup
- Output:
- None; memory at pbData is encrypted in place
- Steps:
- Derive hashSeed: hashSeed = (((uint64) pbKeyDerivationArea) + encID) ^ HashSeedMask
- Compute 128-bit hash: hash128 = t1h2 (pbKeyDerivationArea,hashSeed).
- Decompose hash128 into two 64-bit integers: hash128 = hash128_1 || hash128_2
- Create a 256-bit key for ChaCha12: chachaKey = hash128_1 || hash128_2 || (hash128_1 OR hash128_2) || (hash128_1 + hash128_2)
- Encrypt chachaKey by itself using ChaCha12 using hashSeed as an IV: ChaCha256Encrypt (chachaKey, hashSeed, chachaKey)
- Derive the 64-bit IV for ChaCha12: chachaIV = (((uint64) pbKeyDerivationArea) + encID) ^ CipherIVMask
- Encrypt memory at pbData using ChaCha12: ChaCha256Encrypt (chachaKey, chachaIV, pbData)
- Securely erase temporary values
It's important to note that, due to ChaCha12 being a stream cipher, encryption and decryption processes are identical, and the VcProtectMemory
function can be used for both.
For a deeper understanding and a look into the codebase, one can visit the VeraCrypt repository and explore the mentioned functions in the src/Common/Crypto.c
file.
Starting from version 1.24, VeraCrypt has integrated a mechanism that detects the insertion of new devices into the system when System Encryption is active. If a new device is inserted, master keys are immediately purged from memory, resulting in a Windows BSOD. This protects against attacks using specialized devices to extract memory from running systems. However, for maximum efficiency, this feature should be paired with RAM encryption.
To enable this feature, navigate to the menu System -> Settings and check the "Clear encryption keys from memory if a new device is inserted" option.
The Windows Hibernate and Fast Startup features save the content of RAM to the hard drive. In the context of VeraCrypt's RAM Encryption, supporting these features presents a significant challenge, namely a chicken-egg problem.
To maintain security, the large memory region used for key derivation in RAM Encryption would have to be stored in an encrypted format, separate from the usual VeraCrypt encryption applied to the current drive. This separate encrypted storage must also be unlockable using the same password as the one used for Pre-Boot Authentication. Moreover, this process must happen early in the boot sequence before filesystem access is available, necessitating the raw storage of encrypted data in specific sectors of a different disk.
While this is technically feasible, the complexity and user-unfriendliness of such a solution make it impractical for standard deployments. Therefore, enabling RAM Encryption necessitates the disabling of the Windows Hibernate and Fast Startup features.