From 518460d44c4f862f50e45847ca3c501d55c1e5d5 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 26 Jan 2014 20:30:06 +0000 Subject: [PATCH] [KSECDD] - Fix a typo in KsecQueryVolumeInformation, noticed by Michael Fritscher - Implement KsecGatherEntropyData, which will be used in generation of cryptographically secure random numbers according to FIPS 186-2. Based on information from http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx svn path=/trunk/; revision=61842 --- reactos/drivers/crypto/ksecdd/CMakeLists.txt | 5 + reactos/drivers/crypto/ksecdd/dispatch.c | 2 +- reactos/drivers/crypto/ksecdd/ksecdd.h | 32 ++++ reactos/drivers/crypto/ksecdd/random.c | 155 +++++++++++++++++++ 4 files changed, 193 insertions(+), 1 deletion(-) diff --git a/reactos/drivers/crypto/ksecdd/CMakeLists.txt b/reactos/drivers/crypto/ksecdd/CMakeLists.txt index 070f9278223..eb8a3184701 100644 --- a/reactos/drivers/crypto/ksecdd/CMakeLists.txt +++ b/reactos/drivers/crypto/ksecdd/CMakeLists.txt @@ -1,6 +1,10 @@ spec2def(ksecdd.sys ksecdd.spec) + +include_directories( + ${REACTOS_SOURCE_DIR}/lib/cryptlib) + list(APPEND SOURCE ksecdd.c dispatch.c @@ -9,6 +13,7 @@ list(APPEND SOURCE ksecdd.rc) add_library(ksecdd SHARED ${SOURCE}) +target_link_libraries(ksecdd cryptlib pseh) set_module_type(ksecdd kernelmodedriver) add_importlibs(ksecdd ntoskrnl hal) add_cd_file(TARGET ksecdd DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/reactos/drivers/crypto/ksecdd/dispatch.c b/reactos/drivers/crypto/ksecdd/dispatch.c index fe6be34331e..34be2fbf974 100644 --- a/reactos/drivers/crypto/ksecdd/dispatch.c +++ b/reactos/drivers/crypto/ksecdd/dispatch.c @@ -60,7 +60,7 @@ KsecQueryVolumeInformation( PFILE_FS_DEVICE_INFORMATION DeviceInformation; /* Only FileFsDeviceInformation is supported */ - if (FsInformationClass == FileFsDeviceInformation) + if (FsInformationClass != FileFsDeviceInformation) { return STATUS_INVALID_INFO_CLASS; } diff --git a/reactos/drivers/crypto/ksecdd/ksecdd.h b/reactos/drivers/crypto/ksecdd/ksecdd.h index 934152d9b91..86eebb4d592 100644 --- a/reactos/drivers/crypto/ksecdd/ksecdd.h +++ b/reactos/drivers/crypto/ksecdd/ksecdd.h @@ -8,11 +8,43 @@ #define _NO_KSECDD_IMPORT_ #include +#include // 0x390004 #define IOCTL_KSEC_GEN_RANDOM \ CTL_CODE(FILE_DEVICE_KSEC, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS) +#if defined(_M_IX86) || defined(_M_AMD64) +typedef struct _KSEC_MACHINE_SPECIFIC_COUNTERS +{ + ULONG64 Tsc; + ULONG64 Pmc0; + ULONG64 Pmc1; + ULONG64 Ctr0; + ULONG64 Ctr1; +} KSEC_MACHINE_SPECIFIC_COUNTERS, *PKSEC_MACHINE_SPECIFIC_COUNTERS; +#else +typedef ULONG KSEC_MACHINE_SPECIFIC_COUNTERS; +#endif + +typedef struct _KSEC_ENTROPY_DATA +{ + HANDLE CurrentProcessId; + HANDLE CurrentThreadId; + LARGE_INTEGER TickCount; + LARGE_INTEGER SystemTime; + LARGE_INTEGER PerformanceCounter; + LARGE_INTEGER PerformanceFrequency; + UCHAR EnvironmentHash[16]; + KSEC_MACHINE_SPECIFIC_COUNTERS MachineSpecificCounters; + SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemProcessorPerformanceInformation; + SYSTEM_PERFORMANCE_INFORMATION SystemPerformanceInformation; + SYSTEM_EXCEPTION_INFORMATION SystemExceptionInformation; + SYSTEM_LOOKASIDE_INFORMATION SystemLookasideInformation; + SYSTEM_INTERRUPT_INFORMATION SystemInterruptInformation; + SYSTEM_PROCESS_INFORMATION SystemProcessInformation; +} KSEC_ENTROPY_DATA, *PKSEC_ENTROPY_DATA; + NTSTATUS NTAPI KsecDdDispatch( diff --git a/reactos/drivers/crypto/ksecdd/random.c b/reactos/drivers/crypto/ksecdd/random.c index fdf724d48db..392ad0f70ca 100644 --- a/reactos/drivers/crypto/ksecdd/random.c +++ b/reactos/drivers/crypto/ksecdd/random.c @@ -9,6 +9,10 @@ /* INCLUDES *******************************************************************/ #include "ksecdd.h" +#include +#include +#include +#include #define NDEBUG #include @@ -48,3 +52,154 @@ KsecGenRandom( return STATUS_SUCCESS; } + +VOID +NTAPI +KsecReadMachineSpecificCounters( + _Out_ PKSEC_MACHINE_SPECIFIC_COUNTERS MachineSpecificCounters) +{ +#if defined(_M_IX86) || defined(_M_AMD64) + /* Check if RDTSC is available */ + if (ExIsProcessorFeaturePresent(PF_RDTSC_INSTRUCTION_AVAILABLE)) + { + /* Read the TSC value */ + MachineSpecificCounters->Tsc = __rdtsc(); + } + + /* Read the CPU event counter MSRs */ + MachineSpecificCounters->Ctr0 = __readmsr(0x12); + MachineSpecificCounters->Ctr1 = __readmsr(0x13); + + /* Check if this is an MMX capable CPU */ + if (ExIsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) + { + /* Read the CPU performance counters 0 and 1 */ + MachineSpecificCounters->Pmc0 = __readpmc(0); + MachineSpecificCounters->Pmc1 = __readpmc(1); + } +#else + #error Implement me! +#endif +} + +/*! + * \see http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx + */ +NTSTATUS +NTAPI +KsecGatherEntropyData( + PKSEC_ENTROPY_DATA EntropyData) +{ + MD4_CTX Md4Context; + PTEB Teb; + PPEB Peb; + PWSTR String; + ULONG ReturnLength; + NTSTATUS Status; + + /* Query some generic values */ + EntropyData->CurrentProcessId = PsGetCurrentProcessId(); + EntropyData->CurrentThreadId = PsGetCurrentThreadId(); + KeQueryTickCount(&EntropyData->TickCount); + KeQuerySystemTime(&EntropyData->SystemTime); + EntropyData->PerformanceCounter = KeQueryPerformanceCounter( + &EntropyData->PerformanceFrequency); + + /* Check if we have a TEB/PEB for the process environment */ + Teb = PsGetCurrentThread()->Tcb.Teb; + if (Teb != NULL) + { + Peb = Teb->ProcessEnvironmentBlock; + + /* Initialize the MD4 context */ + MD4Init(&Md4Context); + _SEH2_TRY + { + /* Get the end of the environment */ + String = Peb->ProcessParameters->Environment; + while (*String) + { + String += wcslen(String) + 1; + } + + /* Update the MD4 context from the environment data */ + MD4Update(&Md4Context, + (PUCHAR)Peb->ProcessParameters->Environment, + (PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Simply ignore the exception */ + } + _SEH2_END; + + /* Finalize and copy the MD4 hash */ + MD4Final(&Md4Context); + RtlCopyMemory(&EntropyData->EnvironmentHash, Md4Context.digest, 16); + } + + /* Read some machine specific hardware counters */ + KsecReadMachineSpecificCounters(&EntropyData->MachineSpecificCounters); + + /* Query processor performance information */ + Status = ZwQuerySystemInformation(SystemProcessorPerformanceInformation, + &EntropyData->SystemProcessorPerformanceInformation, + sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Query system performance information */ + Status = ZwQuerySystemInformation(SystemPerformanceInformation, + &EntropyData->SystemPerformanceInformation, + sizeof(SYSTEM_PERFORMANCE_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Query exception information */ + Status = ZwQuerySystemInformation(SystemExceptionInformation, + &EntropyData->SystemExceptionInformation, + sizeof(SYSTEM_EXCEPTION_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Query lookaside information */ + Status = ZwQuerySystemInformation(SystemLookasideInformation, + &EntropyData->SystemLookasideInformation, + sizeof(SYSTEM_LOOKASIDE_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Query interrupt information */ + Status = ZwQuerySystemInformation(SystemInterruptInformation, + &EntropyData->SystemInterruptInformation, + sizeof(SYSTEM_INTERRUPT_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Query process information */ + Status = ZwQuerySystemInformation(SystemProcessInformation, + &EntropyData->SystemProcessInformation, + sizeof(SYSTEM_PROCESS_INFORMATION), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + return STATUS_SUCCESS; +} -- 2.17.1