0dc1b59cfcec1936b58e913031e04c19c2331fd3
[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 #if 0 // FIXME: investigate what the requirements are for these
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 #endif
79 #else
80 #error Implement me!
81 #endif
82 }
83
84 /*!
85 * \see http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx
86 */
87 NTSTATUS
88 NTAPI
89 KsecGatherEntropyData(
90 PKSEC_ENTROPY_DATA EntropyData)
91 {
92 MD4_CTX Md4Context;
93 PTEB Teb;
94 PPEB Peb;
95 PWSTR String;
96 SIZE_T ReturnLength;
97 NTSTATUS Status;
98
99 /* Query some generic values */
100 EntropyData->CurrentProcessId = PsGetCurrentProcessId();
101 EntropyData->CurrentThreadId = PsGetCurrentThreadId();
102 KeQueryTickCount(&EntropyData->TickCount);
103 KeQuerySystemTime(&EntropyData->SystemTime);
104 EntropyData->PerformanceCounter = KeQueryPerformanceCounter(
105 &EntropyData->PerformanceFrequency);
106
107 /* Check if we have a TEB/PEB for the process environment */
108 Teb = PsGetCurrentThread()->Tcb.Teb;
109 if (Teb != NULL)
110 {
111 Peb = Teb->ProcessEnvironmentBlock;
112
113 /* Initialize the MD4 context */
114 MD4Init(&Md4Context);
115 _SEH2_TRY
116 {
117 /* Get the end of the environment */
118 String = Peb->ProcessParameters->Environment;
119 while (*String)
120 {
121 String += wcslen(String) + 1;
122 }
123
124 /* Update the MD4 context from the environment data */
125 MD4Update(&Md4Context,
126 (PUCHAR)Peb->ProcessParameters->Environment,
127 (ULONG)((PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment));
128 }
129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
130 {
131 /* Simply ignore the exception */
132 }
133 _SEH2_END;
134
135 /* Finalize and copy the MD4 hash */
136 MD4Final(&Md4Context);
137 RtlCopyMemory(&EntropyData->EnvironmentHash, Md4Context.digest, 16);
138 }
139
140 /* Read some machine specific hardware counters */
141 KsecReadMachineSpecificCounters(&EntropyData->MachineSpecificCounters);
142
143 /* Query processor performance information */
144 Status = ZwQuerySystemInformation(SystemProcessorPerformanceInformation,
145 &EntropyData->SystemProcessorPerformanceInformation,
146 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
147 &ReturnLength);
148 if (!NT_SUCCESS(Status))
149 {
150 return Status;
151 }
152
153 /* Query system performance information */
154 Status = ZwQuerySystemInformation(SystemPerformanceInformation,
155 &EntropyData->SystemPerformanceInformation,
156 sizeof(SYSTEM_PERFORMANCE_INFORMATION),
157 &ReturnLength);
158 if (!NT_SUCCESS(Status))
159 {
160 return Status;
161 }
162
163 /* Query exception information */
164 Status = ZwQuerySystemInformation(SystemExceptionInformation,
165 &EntropyData->SystemExceptionInformation,
166 sizeof(SYSTEM_EXCEPTION_INFORMATION),
167 &ReturnLength);
168 if (!NT_SUCCESS(Status))
169 {
170 return Status;
171 }
172
173 /* Query lookaside information */
174 Status = ZwQuerySystemInformation(SystemLookasideInformation,
175 &EntropyData->SystemLookasideInformation,
176 sizeof(SYSTEM_LOOKASIDE_INFORMATION),
177 &ReturnLength);
178 if (!NT_SUCCESS(Status))
179 {
180 return Status;
181 }
182
183 /* Query interrupt information */
184 Status = ZwQuerySystemInformation(SystemInterruptInformation,
185 &EntropyData->SystemInterruptInformation,
186 sizeof(SYSTEM_INTERRUPT_INFORMATION),
187 &ReturnLength);
188 if (!NT_SUCCESS(Status))
189 {
190 return Status;
191 }
192
193 /* Query process information */
194 Status = ZwQuerySystemInformation(SystemProcessInformation,
195 &EntropyData->SystemProcessInformation,
196 sizeof(SYSTEM_PROCESS_INFORMATION),
197 &ReturnLength);
198 if (!NT_SUCCESS(Status))
199 {
200 return Status;
201 }
202
203 return STATUS_SUCCESS;
204 }