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