From c0f8179f2af7cdaa0a098b5ad5ea9bdba654274e Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 29 Sep 2023 22:26:54 +0200 Subject: Windows: enhancement to RAM encryption - use a more standard-looking memory value tag instead of fully random one that will look suspicious and outstanding - If we fail to allocate 1MiB for derivation area, we device the size by two in a loop until we succeed. This is better than falling back directly to 8KiB size - Better method to derive actual encryption key: instead of simply duplicating 128bit key value, we combine a xor addition and self-encryption to build a 256-bit key - use both encID and pbKeyDerivationArea to derive IV for encryption and not only endID --- src/Common/Crypto.c | 72 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 17 deletions(-) (limited to 'src/Common') 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); -- cgit v1.2.3