VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/Crypto.c')
-rw-r--r--src/Common/Crypto.c72
1 files changed, 55 insertions, 17 deletions
diff --git a/src/Common/Crypto.c b/src/Common/Crypto.c
index e87aea35..38af7fe5 100644
--- a/src/Common/Crypto.c
+++ b/src/Common/Crypto.c
@@ -1305,8 +1305,8 @@ BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
ChaCha20RngCtx ctx;
byte pbSeed[CHACHA20RNG_KEYSZ + CHACHA20RNG_IVSZ];
#ifdef TC_WINDOWS_DRIVER
- byte i, tagLength;
-
+ byte i;
+ char randomStr[4];
Dump ("InitializeSecurityParameters BEGIN\n");
#endif
@@ -1315,28 +1315,57 @@ BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
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
+ /* Generate random value for tag that is similar to pool tag values used by Windows kernel.
+ * Fully random tag would be too suspicious and outstanding.
+ * First character is always a capital letter.
+ * Second character is a letter, lowercase or uppercase.
+ * Third character is a letter, lowercase or uppercase.
+ * Fourth character is a letter or a digit.
*/
+
+ /* 1. First character (Capital Letter) */
+ randomStr[0] = 'A' + GetRandomIndex(&ctx, 26);
+
+ /* 2. Second character (Letter) */
+ i = GetRandomIndex(&ctx, 52);
+ if (i < 26)
+ randomStr[1] = 'A' + i;
+ else
+ randomStr[1] = 'a' + (i - 26);
+
+ /* 3. Third character (Letter) */
+ i = GetRandomIndex(&ctx, 52);
+ if (i < 26)
+ randomStr[2] = 'A' + i;
+ else
+ randomStr[2] = 'a' + (i - 26);
+
+ /* 4. Fourth character (Letter or Digit) */
+ i = GetRandomIndex(&ctx, 62);
+ if (i < 26)
+ randomStr[3] = 'A' + i;
+ else if (i < 52)
+ randomStr[3] = 'a' + (i - 26);
+ else
+ randomStr[3] = '0' + (i - 52);
+
+ /* combine all characters in reverse order as explained in MSDN */
AllocTag = 0;
- for (i = 0; i < tagLength; i++)
+ for (i = 0; i < 4; i++)
{
- AllocTag = (AllocTag << 8) + (((ULONG) GetRandomIndex (&ctx, 95)) + 0x20);
+ AllocTag = (AllocTag << 8) + randomStr[3-i];
}
#endif
cbKeyDerivationArea = 1024 * 1024;
- pbKeyDerivationArea = (byte*) TCalloc(cbKeyDerivationArea);
- if (!pbKeyDerivationArea)
+ do
{
- cbKeyDerivationArea = 2 * PAGE_SIZE;
pbKeyDerivationArea = (byte*) TCalloc(cbKeyDerivationArea);
- }
+ if (!pbKeyDerivationArea)
+ cbKeyDerivationArea >>= 1;
+ } while (!pbKeyDerivationArea && (cbKeyDerivationArea >= (2*PAGE_SIZE)));
if (!pbKeyDerivationArea)
{
@@ -1357,7 +1386,7 @@ BOOL InitializeSecurityParameters(GetRandSeedFn rngCallback)
FAST_ERASE64 (pbSeed, sizeof (pbSeed));
burn (&ctx, sizeof (ctx));
#ifdef TC_WINDOWS_DRIVER
- burn (&tagLength, 1);
+ burn (randomStr, sizeof(randomStr));
Dump ("InitializeSecurityParameters return=TRUE END\n");
#endif
@@ -1402,11 +1431,20 @@ void VcProtectMemory (uint64 encID, unsigned char* pbData, size_t cbData,
hashLow = t1ha2_atonce128(&hashHigh, pbKeyDerivationArea, cbKeyDerivationArea, hashSeed);
/* set the key to the hash result */
- pbKey[0] = pbKey[2] = hashLow;
- pbKey[1] = pbKey[3] = hashHigh;
+ pbKey[0] = hashLow;
+ pbKey[1] = hashHigh;
+ /* we now have a 128-bit key and we will expand it to 256-bit by using ChaCha12 cipher */
+ /* first we need to generate a the other 128-bit half of the key */
+ pbKey[2] = hashLow ^ hashHigh;
+ pbKey[3] = hashLow + hashHigh;
+
+ /* Initialize ChaCha12 cipher */
+ ChaCha256Init (&ctx, (unsigned char*) pbKey, (unsigned char*) &hashSeed, 12);
+ /* encrypt the key by itself */
+ ChaCha256Encrypt (&ctx, (unsigned char*) pbKey, sizeof(pbKey), (unsigned char*) pbKey);
/* Initialize ChaCha12 cipher */
- cipherIV = encID ^ CipherIVMask;
+ cipherIV = (((uint64) pbKeyDerivationArea) + encID) ^ CipherIVMask;
ChaCha256Init (&ctx, (unsigned char*) pbKey, (unsigned char*) &cipherIV, 12);
ChaCha256Encrypt (&ctx, pbData, cbData, pbData);