From ba5da0946c3abaa93d1161ca512c3c326cda3736 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 8 Feb 2019 01:48:12 +0100 Subject: Windows: Add implementation of ChaCha20 based random generator. Use it for driver need of random bytes (currently only wipe bytes but more to come later). --- src/Driver/DriveFilter.c | 42 ++++++--------------------- src/Driver/Driver.vcxproj | 4 +++ src/Driver/Driver.vcxproj.filters | 12 ++++++++ src/Driver/Ntdriver.c | 60 +++++++++++++++++++++++++++++++++++++++ src/Driver/Ntdriver.h | 1 + 5 files changed, 86 insertions(+), 33 deletions(-) (limited to 'src/Driver') diff --git a/src/Driver/DriveFilter.c b/src/Driver/DriveFilter.c index 6228009f..3c7687f8 100644 --- a/src/Driver/DriveFilter.c +++ b/src/Driver/DriveFilter.c @@ -29,6 +29,7 @@ #include "Boot/Windows/BootCommon.h" #include "cpu.h" #include "rdrand.h" +#include "chachaRng.h" static BOOL DeviceFilterActive = FALSE; @@ -1521,42 +1522,17 @@ static VOID SetupThreadProc (PVOID threadArg) // generate real random values for wipeRandChars and // wipeRandCharsUpdate instead of relying on uninitialized stack memory - LARGE_INTEGER iSeed; - byte digest[WHIRLPOOL_DIGESTSIZE]; - WHIRLPOOL_CTX tctx; - -#ifndef _WIN64 - KFLOATING_SAVE floatingPointState; - NTSTATUS saveStatus = STATUS_INVALID_PARAMETER; - if (HasISSE()) - saveStatus = KeSaveFloatingPointState (&floatingPointState); -#endif + ChaCha20RngCtx rngCtx; + byte pbSeed[CHACHA20RNG_KEYSZ + CHACHA20RNG_IVSZ]; - KeQuerySystemTime( &iSeed ); - WHIRLPOOL_init (&tctx); - WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); - // use RDSEED or RDRAND from CPU as source of entropy if enabled - if ( IsCpuRngEnabled() && - ( (HasRDSEED() && RDSEED_getBytes (digest, sizeof (digest))) - || (HasRDRAND() && RDRAND_getBytes (digest, sizeof (digest))) - )) - { - WHIRLPOOL_add (digest, sizeof(digest), &tctx); - } - WHIRLPOOL_finalize (&tctx, digest); + GetDriverRandomSeed (pbSeed, sizeof (pbSeed)); + ChaCha20RngInit (&rngCtx, pbSeed, GetDriverRandomSeed, 0); -#if !defined (_WIN64) - if (NT_SUCCESS (saveStatus)) - KeRestoreFloatingPointState (&floatingPointState); -#endif - - memcpy (wipeRandChars, digest, TC_WIPE_RAND_CHAR_COUNT); - memcpy (wipeRandCharsUpdate, &digest[WHIRLPOOL_DIGESTSIZE - TC_WIPE_RAND_CHAR_COUNT], TC_WIPE_RAND_CHAR_COUNT); + ChaCha20RngGetBytes (&rngCtx, wipeRandChars, TC_WIPE_RAND_CHAR_COUNT); + ChaCha20RngGetBytes (&rngCtx, wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT); - burn (digest, WHIRLPOOL_DIGESTSIZE); - burn (&tctx, sizeof (tctx)); - - burn (&iSeed, sizeof(iSeed)); + burn (&rngCtx, sizeof (rngCtx)); + FAST_ERASE64 (pbSeed, sizeof (pbSeed)); SetupResult = STATUS_UNSUCCESSFUL; diff --git a/src/Driver/Driver.vcxproj b/src/Driver/Driver.vcxproj index 894873d5..7104be84 100644 --- a/src/Driver/Driver.vcxproj +++ b/src/Driver/Driver.vcxproj @@ -193,9 +193,13 @@ BuildDriver.cmd -rebuild -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Cry + + + + diff --git a/src/Driver/Driver.vcxproj.filters b/src/Driver/Driver.vcxproj.filters index 74cd18e8..20227b48 100644 --- a/src/Driver/Driver.vcxproj.filters +++ b/src/Driver/Driver.vcxproj.filters @@ -111,6 +111,18 @@ Source Files\Crypto + + Source Files\Crypto + + + Source Files\Crypto + + + Source Files\Crypto + + + Source Files\Crypto + diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 7e3a08bd..9719c91b 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -30,6 +30,8 @@ #include "Cache.h" #include "Volumes.h" #include "VolumeFilter.h" +#include "cpu.h" +#include "rdrand.h" #include #include @@ -143,6 +145,64 @@ ULONG ExDefaultMdlProtection = 0; PDEVICE_OBJECT VirtualVolumeDeviceObjects[MAX_MOUNTED_VOLUME_DRIVE_NUMBER + 1]; +void GetDriverRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed) +{ + LARGE_INTEGER iSeed, iSeed2; + byte digest[WHIRLPOOL_DIGESTSIZE]; + WHIRLPOOL_CTX tctx; + size_t count; + +#ifndef _WIN64 + KFLOATING_SAVE floatingPointState; + NTSTATUS saveStatus = STATUS_INVALID_PARAMETER; + if (HasISSE()) + saveStatus = KeSaveFloatingPointState (&floatingPointState); +#endif + + while (cbRandSeed) + { + WHIRLPOOL_init (&tctx); + // we hash current content of digest buffer which is initialized the first time + WHIRLPOOL_add (digest, WHIRLPOOL_DIGESTSIZE, &tctx); + + // we use various time information as source of entropy + KeQuerySystemTime( &iSeed ); + WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + iSeed = KeQueryPerformanceCounter (&iSeed2); + WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + WHIRLPOOL_add ((unsigned char *) &(iSeed2.QuadPart), sizeof(iSeed2.QuadPart), &tctx); + iSeed.QuadPart = KeQueryInterruptTime (); + WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + + // use RDSEED or RDRAND from CPU as source of entropy if enabled + if ( IsCpuRngEnabled() && + ( (HasRDSEED() && RDSEED_getBytes (digest, sizeof (digest))) + || (HasRDRAND() && RDRAND_getBytes (digest, sizeof (digest))) + )) + { + WHIRLPOOL_add (digest, sizeof(digest), &tctx); + } + WHIRLPOOL_finalize (&tctx, digest); + + count = VC_MIN (cbRandSeed, sizeof (digest)); + + // copy digest value to seed buffer + memcpy (pbRandSeed, digest, count); + cbRandSeed -= count; + pbRandSeed += count; + } + +#if !defined (_WIN64) + if (NT_SUCCESS (saveStatus)) + KeRestoreFloatingPointState (&floatingPointState); +#endif + + FAST_ERASE64 (digest, sizeof (digest)); + FAST_ERASE64 (&iSeed.QuadPart, 8); + FAST_ERASE64 (&iSeed2.QuadPart, 8); + burn (&tctx, sizeof(tctx)); +} + NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { diff --git a/src/Driver/Ntdriver.h b/src/Driver/Ntdriver.h index 42b0919d..2e4d6555 100644 --- a/src/Driver/Ntdriver.h +++ b/src/Driver/Ntdriver.h @@ -191,6 +191,7 @@ void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter); int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter); BOOL IsOSAtLeast (OSVersionEnum reqMinOS); PDEVICE_OBJECT GetVirtualVolumeDeviceObject (int driveNumber); +void GetDriverRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed); #define TC_BUG_CHECK(status) KeBugCheckEx (SECURITY_SYSTEM, __LINE__, (ULONG_PTR) status, 0, 'VC') -- cgit v1.2.3