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