[KSECDD]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 26 Jan 2014 20:30:06 +0000 (20:30 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 26 Jan 2014 20:30:06 +0000 (20:30 +0000)
- 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
reactos/drivers/crypto/ksecdd/dispatch.c
reactos/drivers/crypto/ksecdd/ksecdd.h
reactos/drivers/crypto/ksecdd/random.c

index 070f927..eb8a318 100644 (file)
@@ -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)
index fe6be34..34be2fb 100644 (file)
@@ -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;
     }
index 934152d..86eebb4 100644 (file)
@@ -8,11 +8,43 @@
 
 #define _NO_KSECDD_IMPORT_
 #include <ntifs.h>
+#include <ndk/extypes.h>
 
 // 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(
index fdf724d..392ad0f 100644 (file)
@@ -9,6 +9,10 @@
 /* INCLUDES *******************************************************************/
 
 #include "ksecdd.h"
+#include <ndk/exfuncs.h>
+#include <ndk/kefuncs.h>
+#include <pseh/pseh2.h>
+#include <md4.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -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;
+}