6e5a795fad34ff9a1afb9947cedcd5431b5ec223
[reactos.git] / reactos / drivers / crypto / ksecdd / random.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Drivers
4 * PURPOSE: Kernel Security Support Provider Interface Driver
5 *
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "ksecdd.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 /* GLOBALS ********************************************************************/
18
19 static ULONG KsecRandomSeed = 0x62b409a1;
20
21
22 /* FUNCTIONS ******************************************************************/
23
24 NTSTATUS
25 NTAPI
26 KsecGenRandom(
27 PVOID Buffer,
28 SIZE_T Length)
29 {
30 LARGE_INTEGER TickCount;
31 ULONG i, RandomValue;
32 PULONG P;
33
34 /* Try to generate a more random seed */
35 KeQueryTickCount(&TickCount);
36 KsecRandomSeed ^= _rotl(TickCount.LowPart, (KsecRandomSeed % 23));
37
38 P = Buffer;
39 for (i = 0; i < Length / sizeof(ULONG); i++)
40 {
41 P[i] = RtlRandomEx(&KsecRandomSeed);
42 }
43
44 Length &= (sizeof(ULONG) - 1);
45 if (Length > 0)
46 {
47 RandomValue = RtlRandomEx(&KsecRandomSeed);
48 RtlCopyMemory(&P[i], &RandomValue, Length);
49 }
50
51 return STATUS_SUCCESS;
52 }
53
54 VOID
55 NTAPI
56 KsecReadMachineSpecificCounters(
57 _Out_ PKSEC_MACHINE_SPECIFIC_COUNTERS MachineSpecificCounters)
58 {
59 #if defined(_M_IX86) || defined(_M_AMD64)
60 /* Check if RDTSC is available */
61 if (ExIsProcessorFeaturePresent(PF_RDTSC_INSTRUCTION_AVAILABLE))
62 {
63 /* Read the TSC value */
64 MachineSpecificCounters->Tsc = __rdtsc();
65 }
66
67 /* Read the CPU event counter MSRs */
68 //MachineSpecificCounters->Ctr0 = __readmsr(0x12);
69 //MachineSpecificCounters->Ctr1 = __readmsr(0x13);
70
71 /* Check if this is an MMX capable CPU */
72 if (ExIsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
73 {
74 /* Read the CPU performance counters 0 and 1 */
75 MachineSpecificCounters->Pmc0 = __readpmc(0);
76 MachineSpecificCounters->Pmc1 = __readpmc(1);
77 }
78 #else
79 #error Implement me!
80 #endif
81 }
82
83 /*!
84 * \see http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx
85 */
86 NTSTATUS
87 NTAPI
88 KsecGatherEntropyData(
89 PKSEC_ENTROPY_DATA EntropyData)
90 {
91 MD4_CTX Md4Context;
92 PTEB Teb;
93 PPEB Peb;
94 PWSTR String;
95 SIZE_T ReturnLength;
96 NTSTATUS Status;
97
98 /* Query some generic values */
99 EntropyData->CurrentProcessId = PsGetCurrentProcessId();
100 EntropyData->CurrentThreadId = PsGetCurrentThreadId();
101 KeQueryTickCount(&EntropyData->TickCount);
102 KeQuerySystemTime(&EntropyData->SystemTime);
103 EntropyData->PerformanceCounter = KeQueryPerformanceCounter(
104 &EntropyData->PerformanceFrequency);
105
106 /* Check if we have a TEB/PEB for the process environment */
107 Teb = PsGetCurrentThread()->Tcb.Teb;
108 if (Teb != NULL)
109 {
110 Peb = Teb->ProcessEnvironmentBlock;
111
112 /* Initialize the MD4 context */
113 MD4Init(&Md4Context);
114 _SEH2_TRY
115 {
116 /* Get the end of the environment */
117 String = Peb->ProcessParameters->Environment;
118 while (*String)
119 {
120 String += wcslen(String) + 1;
121 }
122
123 /* Update the MD4 context from the environment data */
124 MD4Update(&Md4Context,
125 (PUCHAR)Peb->ProcessParameters->Environment,
126 (ULONG)((PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment));
127 }
128 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
129 {
130 /* Simply ignore the exception */
131 }
132 _SEH2_END;
133
134 /* Finalize and copy the MD4 hash */
135 MD4Final(&Md4Context);
136 RtlCopyMemory(&EntropyData->EnvironmentHash, Md4Context.digest, 16);
137 }
138
139 /* Read some machine specific hardware counters */
140 KsecReadMachineSpecificCounters(&EntropyData->MachineSpecificCounters);
141
142 /* Query processor performance information */
143 Status = ZwQuerySystemInformation(SystemProcessorPerformanceInformation,
144 &EntropyData->SystemProcessorPerformanceInformation,
145 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
146 &ReturnLength);
147 if (!NT_SUCCESS(Status))
148 {
149 return Status;
150 }
151
152 /* Query system performance information */
153 Status = ZwQuerySystemInformation(SystemPerformanceInformation,
154 &EntropyData->SystemPerformanceInformation,
155 sizeof(SYSTEM_PERFORMANCE_INFORMATION),
156 &ReturnLength);
157 if (!NT_SUCCESS(Status))
158 {
159 return Status;
160 }
161
162 /* Query exception information */
163 Status = ZwQuerySystemInformation(SystemExceptionInformation,
164 &EntropyData->SystemExceptionInformation,
165 sizeof(SYSTEM_EXCEPTION_INFORMATION),
166 &ReturnLength);
167 if (!NT_SUCCESS(Status))
168 {
169 return Status;
170 }
171
172 /* Query lookaside information */
173 Status = ZwQuerySystemInformation(SystemLookasideInformation,
174 &EntropyData->SystemLookasideInformation,
175 sizeof(SYSTEM_LOOKASIDE_INFORMATION),
176 &ReturnLength);
177 if (!NT_SUCCESS(Status))
178 {
179 return Status;
180 }
181
182 /* Query interrupt information */
183 Status = ZwQuerySystemInformation(SystemInterruptInformation,
184 &EntropyData->SystemInterruptInformation,
185 sizeof(SYSTEM_INTERRUPT_INFORMATION),
186 &ReturnLength);
187 if (!NT_SUCCESS(Status))
188 {
189 return Status;
190 }
191
192 /* Query process information */
193 Status = ZwQuerySystemInformation(SystemProcessInformation,
194 &EntropyData->SystemProcessInformation,
195 sizeof(SYSTEM_PROCESS_INFORMATION),
196 &ReturnLength);
197 if (!NT_SUCCESS(Status))
198 {
199 return Status;
200 }
201
202 return STATUS_SUCCESS;
203 }