1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Drivers
3c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
4c2c66affSColin Finck * PURPOSE: Kernel Security Support Provider Interface Driver
5c2c66affSColin Finck *
6c2c66affSColin Finck * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES *******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck #include "ksecdd.h"
12c2c66affSColin Finck
13c2c66affSColin Finck MD5_CTX KsecLoadTimeStartMd5s[2];
14c2c66affSColin Finck DES3_KEY KsecGlobalDes3Key;
15c2c66affSColin Finck AES_KEY KsecGlobalAesKey;
16c2c66affSColin Finck
17c2c66affSColin Finck typedef struct _KSEC_PROCESS_DATA
18c2c66affSColin Finck {
19c2c66affSColin Finck PEPROCESS Process;
20c2c66affSColin Finck HANDLE ProcessId;
21c2c66affSColin Finck LONGLONG CreateTime;
22c2c66affSColin Finck ULONG_PTR DirectoryTableBase;
23c2c66affSColin Finck } KSEC_PROCESS_DATA, *PKSEC_PROCESS_DATA;
24c2c66affSColin Finck
25c2c66affSColin Finck typedef struct _KSEC_LOGON_DATA
26c2c66affSColin Finck {
27c2c66affSColin Finck LUID LogonId;
28c2c66affSColin Finck } KSEC_LOGON_DATA, *PKSEC_LOGON_DATA;
29c2c66affSColin Finck
30*ab43f869STimo Kreuzer #if 0
31*ab43f869STimo Kreuzer void PrintKeyData(PUCHAR KeyData)
32*ab43f869STimo Kreuzer {
33*ab43f869STimo Kreuzer ULONG i;
34*ab43f869STimo Kreuzer for (i = 0; i < 32; i++)
35*ab43f869STimo Kreuzer {
36*ab43f869STimo Kreuzer DbgPrint("%02X", KeyData[i]);
37*ab43f869STimo Kreuzer }
38*ab43f869STimo Kreuzer DbgPrint("\n");
39*ab43f869STimo Kreuzer }
40*ab43f869STimo Kreuzer #endif
41*ab43f869STimo Kreuzer
42c2c66affSColin Finck VOID
43c2c66affSColin Finck NTAPI
KsecInitializeEncryptionSupport(VOID)44c2c66affSColin Finck KsecInitializeEncryptionSupport (
45c2c66affSColin Finck VOID)
46c2c66affSColin Finck {
47c2c66affSColin Finck KSEC_ENTROPY_DATA EntropyData;
48c2c66affSColin Finck MD5_CTX Md5Context;
49c2c66affSColin Finck UCHAR KeyDataBuffer[32];
50c2c66affSColin Finck
51c2c66affSColin Finck KsecGatherEntropyData(&EntropyData);
52c2c66affSColin Finck MD5Init(&Md5Context);
53c2c66affSColin Finck MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
54c2c66affSColin Finck KsecLoadTimeStartMd5s[0] = Md5Context;
55c2c66affSColin Finck MD5Final(&Md5Context);
56c2c66affSColin Finck RtlCopyMemory(KeyDataBuffer, &Md5Context.digest, 16);
57c2c66affSColin Finck
58c2c66affSColin Finck KsecGatherEntropyData(&EntropyData);
59c2c66affSColin Finck Md5Context = KsecLoadTimeStartMd5s[0];
60c2c66affSColin Finck MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
61c2c66affSColin Finck KsecLoadTimeStartMd5s[1] = Md5Context;
62c2c66affSColin Finck MD5Final(&Md5Context);
63c2c66affSColin Finck RtlCopyMemory(&KeyDataBuffer[16], &Md5Context.digest, 16);
64c2c66affSColin Finck
65c2c66affSColin Finck /* Create the global keys */
66c2c66affSColin Finck aes_setup(KeyDataBuffer, 32, 0, &KsecGlobalAesKey);
67c2c66affSColin Finck des3_setup(KeyDataBuffer, 24, 0, &KsecGlobalDes3Key);
68c2c66affSColin Finck
69c2c66affSColin Finck /* Erase the temp data */
70c2c66affSColin Finck RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
71c2c66affSColin Finck RtlSecureZeroMemory(&Md5Context, sizeof(Md5Context));
72c2c66affSColin Finck }
73c2c66affSColin Finck
74c2c66affSColin Finck static
75c2c66affSColin Finck VOID
KsecGetKeyData(_Out_ UCHAR KeyData[32],_In_ ULONG OptionFlags)76c2c66affSColin Finck KsecGetKeyData (
77c2c66affSColin Finck _Out_ UCHAR KeyData[32],
78c2c66affSColin Finck _In_ ULONG OptionFlags)
79c2c66affSColin Finck {
80c2c66affSColin Finck MD5_CTX Md5Contexts[2];
81c2c66affSColin Finck KSEC_PROCESS_DATA ProcessData;
82c2c66affSColin Finck KSEC_LOGON_DATA LogonData;
83c2c66affSColin Finck PEPROCESS CurrentProcess;
84c2c66affSColin Finck PACCESS_TOKEN Token;
85c2c66affSColin Finck
86c2c66affSColin Finck /* We need to generate the key, start with our load MD5s */
87c2c66affSColin Finck Md5Contexts[0] = KsecLoadTimeStartMd5s[0];
88c2c66affSColin Finck Md5Contexts[1] = KsecLoadTimeStartMd5s[1];
89c2c66affSColin Finck
90c2c66affSColin Finck /* Get the current process */
91c2c66affSColin Finck CurrentProcess = PsGetCurrentProcess();
92c2c66affSColin Finck
93c2c66affSColin Finck if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
94c2c66affSColin Finck {
95*ab43f869STimo Kreuzer /* Hash some process specific data to generate the key */
96*ab43f869STimo Kreuzer RtlZeroMemory(&ProcessData, sizeof(ProcessData));
97c2c66affSColin Finck ProcessData.Process = CurrentProcess;
98c2c66affSColin Finck ProcessData.ProcessId = CurrentProcess->UniqueProcessId;
99c2c66affSColin Finck ProcessData.CreateTime = PsGetProcessCreateTimeQuadPart(CurrentProcess);
100c2c66affSColin Finck ProcessData.DirectoryTableBase = CurrentProcess->Pcb.DirectoryTableBase[0];
101c2c66affSColin Finck MD5Update(&Md5Contexts[0], (PVOID)&ProcessData, sizeof(ProcessData));
102c2c66affSColin Finck MD5Update(&Md5Contexts[1], (PVOID)&ProcessData, sizeof(ProcessData));
103c2c66affSColin Finck }
104*ab43f869STimo Kreuzer else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
105c2c66affSColin Finck {
106*ab43f869STimo Kreuzer /* Hash the logon id to generate the key */
107*ab43f869STimo Kreuzer RtlZeroMemory(&LogonData, sizeof(LogonData));
108c2c66affSColin Finck Token = PsReferencePrimaryToken(CurrentProcess);
109c2c66affSColin Finck SeQueryAuthenticationIdToken(Token, &LogonData.LogonId);
110c2c66affSColin Finck PsDereferencePrimaryToken(Token);
111c2c66affSColin Finck MD5Update(&Md5Contexts[0], (PVOID)&LogonData, sizeof(LogonData));
112c2c66affSColin Finck MD5Update(&Md5Contexts[1], (PVOID)&LogonData, sizeof(LogonData));
113c2c66affSColin Finck }
114*ab43f869STimo Kreuzer else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
115*ab43f869STimo Kreuzer {
116*ab43f869STimo Kreuzer /* Use the original MD5s to generate the global key */
117*ab43f869STimo Kreuzer NOTHING;
118*ab43f869STimo Kreuzer }
119*ab43f869STimo Kreuzer else
120*ab43f869STimo Kreuzer {
121*ab43f869STimo Kreuzer /* Must not pass anything else */
122*ab43f869STimo Kreuzer ASSERT(FALSE);
123*ab43f869STimo Kreuzer }
124c2c66affSColin Finck
125c2c66affSColin Finck /* Finalize the MD5s */
126c2c66affSColin Finck MD5Final(&Md5Contexts[0]);
127c2c66affSColin Finck MD5Final(&Md5Contexts[1]);
128c2c66affSColin Finck
129c2c66affSColin Finck /* Copy the md5 data */
130c2c66affSColin Finck RtlCopyMemory(KeyData, &Md5Contexts[0].digest, 16);
131c2c66affSColin Finck RtlCopyMemory((PUCHAR)KeyData + 16, &Md5Contexts[1].digest, 16);
132c2c66affSColin Finck
133c2c66affSColin Finck /* Erase the temp data */
134c2c66affSColin Finck RtlSecureZeroMemory(&Md5Contexts, sizeof(Md5Contexts));
135c2c66affSColin Finck }
136c2c66affSColin Finck
137c2c66affSColin Finck static
138c2c66affSColin Finck VOID
KsecGetDes3Key(_Out_ PDES3_KEY Des3Key,_In_ ULONG OptionFlags)139c2c66affSColin Finck KsecGetDes3Key (
140c2c66affSColin Finck _Out_ PDES3_KEY Des3Key,
141c2c66affSColin Finck _In_ ULONG OptionFlags)
142c2c66affSColin Finck {
143c2c66affSColin Finck UCHAR KeyDataBuffer[32];
144c2c66affSColin Finck
145c2c66affSColin Finck /* Check if the caller allows cross process encryption */
146c2c66affSColin Finck if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
147c2c66affSColin Finck {
148c2c66affSColin Finck /* Return our global cached DES3 key */
149c2c66affSColin Finck *Des3Key = KsecGlobalDes3Key;
150c2c66affSColin Finck }
151c2c66affSColin Finck else
152c2c66affSColin Finck {
153c2c66affSColin Finck /* Setup the key */
154c2c66affSColin Finck KsecGetKeyData(KeyDataBuffer, OptionFlags);
155c2c66affSColin Finck des3_setup(KeyDataBuffer, 24, 0, Des3Key);
156c2c66affSColin Finck
157c2c66affSColin Finck /* Erase the temp data */
158c2c66affSColin Finck RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
159c2c66affSColin Finck }
160c2c66affSColin Finck }
161c2c66affSColin Finck
162c2c66affSColin Finck static
163c2c66affSColin Finck VOID
KsecGetAesKey(_Out_ PAES_KEY AesKey,_In_ ULONG OptionFlags)164c2c66affSColin Finck KsecGetAesKey (
165c2c66affSColin Finck _Out_ PAES_KEY AesKey,
166c2c66affSColin Finck _In_ ULONG OptionFlags)
167c2c66affSColin Finck {
168c2c66affSColin Finck UCHAR KeyDataBuffer[32];
169c2c66affSColin Finck
170c2c66affSColin Finck /* Check if the caller allows cross process encryption */
171c2c66affSColin Finck if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
172c2c66affSColin Finck {
173c2c66affSColin Finck /* Return our global cached AES key */
174c2c66affSColin Finck *AesKey = KsecGlobalAesKey;
175c2c66affSColin Finck }
176c2c66affSColin Finck else
177c2c66affSColin Finck {
178c2c66affSColin Finck /* Setup the key */
179c2c66affSColin Finck KsecGetKeyData(KeyDataBuffer, OptionFlags);
180c2c66affSColin Finck aes_setup(KeyDataBuffer, 32, 0, AesKey);
181c2c66affSColin Finck
182c2c66affSColin Finck /* Erase the temp data */
183c2c66affSColin Finck RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
184c2c66affSColin Finck }
185c2c66affSColin Finck }
186c2c66affSColin Finck
187c2c66affSColin Finck static
188c2c66affSColin Finck VOID
KsecEncryptMemoryDes3(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)189c2c66affSColin Finck KsecEncryptMemoryDes3 (
190c2c66affSColin Finck _Inout_ PVOID Buffer,
191c2c66affSColin Finck _In_ ULONG Length,
192c2c66affSColin Finck _In_ ULONG OptionFlags)
193c2c66affSColin Finck {
194c2c66affSColin Finck UCHAR EncryptedBlockData[8];
195c2c66affSColin Finck DES3_KEY Des3Key;
196c2c66affSColin Finck
197c2c66affSColin Finck /* Get they triple DES key */
198c2c66affSColin Finck KsecGetDes3Key(&Des3Key, OptionFlags);
199c2c66affSColin Finck
200c2c66affSColin Finck /* Do the triple DES encryption */
201c2c66affSColin Finck while (Length >= sizeof(EncryptedBlockData))
202c2c66affSColin Finck {
203c2c66affSColin Finck des3_ecb_encrypt(Buffer, EncryptedBlockData, &Des3Key);
204c2c66affSColin Finck RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
205c2c66affSColin Finck Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
206c2c66affSColin Finck Length -= sizeof(EncryptedBlockData);
207c2c66affSColin Finck }
208c2c66affSColin Finck
209c2c66affSColin Finck /* Erase the key data */
210c2c66affSColin Finck RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));
211c2c66affSColin Finck }
212c2c66affSColin Finck
213c2c66affSColin Finck static
214c2c66affSColin Finck VOID
KsecDecryptMemoryDes3(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)215c2c66affSColin Finck KsecDecryptMemoryDes3 (
216c2c66affSColin Finck _Inout_ PVOID Buffer,
217c2c66affSColin Finck _In_ ULONG Length,
218c2c66affSColin Finck _In_ ULONG OptionFlags)
219c2c66affSColin Finck {
220c2c66affSColin Finck UCHAR BlockData[8];
221c2c66affSColin Finck DES3_KEY Des3Key;
222c2c66affSColin Finck
223c2c66affSColin Finck /* Get they triple DES key */
224c2c66affSColin Finck KsecGetDes3Key(&Des3Key, OptionFlags);
225c2c66affSColin Finck
226c2c66affSColin Finck /* Do the triple DES decryption */
227c2c66affSColin Finck while (Length >= sizeof(BlockData))
228c2c66affSColin Finck {
229c2c66affSColin Finck des3_ecb_decrypt(Buffer, BlockData, &Des3Key);
230c2c66affSColin Finck RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
231c2c66affSColin Finck Buffer = (PUCHAR)Buffer + sizeof(BlockData);
232c2c66affSColin Finck Length -= sizeof(BlockData);
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck /* Erase the key data */
236c2c66affSColin Finck RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));
237c2c66affSColin Finck }
238c2c66affSColin Finck
239c2c66affSColin Finck static
240c2c66affSColin Finck VOID
KsecEncryptMemoryAes(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)241c2c66affSColin Finck KsecEncryptMemoryAes (
242c2c66affSColin Finck _Inout_ PVOID Buffer,
243c2c66affSColin Finck _In_ ULONG Length,
244c2c66affSColin Finck _In_ ULONG OptionFlags)
245c2c66affSColin Finck {
246c2c66affSColin Finck UCHAR EncryptedBlockData[16];
247c2c66affSColin Finck AES_KEY AesKey;
248c2c66affSColin Finck
249c2c66affSColin Finck /* Get they AES key */
250c2c66affSColin Finck KsecGetAesKey(&AesKey, OptionFlags);
251c2c66affSColin Finck
252c2c66affSColin Finck /* Do the AES encryption */
253c2c66affSColin Finck while (Length >= sizeof(EncryptedBlockData))
254c2c66affSColin Finck {
255c2c66affSColin Finck aes_ecb_encrypt(Buffer, EncryptedBlockData, &AesKey);
256c2c66affSColin Finck RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
257c2c66affSColin Finck Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
258c2c66affSColin Finck Length -= sizeof(EncryptedBlockData);
259c2c66affSColin Finck }
260c2c66affSColin Finck
261c2c66affSColin Finck /* Erase the key data */
262c2c66affSColin Finck RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
263c2c66affSColin Finck }
264c2c66affSColin Finck
265c2c66affSColin Finck static
266c2c66affSColin Finck VOID
KsecDecryptMemoryAes(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)267c2c66affSColin Finck KsecDecryptMemoryAes (
268c2c66affSColin Finck _Inout_ PVOID Buffer,
269c2c66affSColin Finck _In_ ULONG Length,
270c2c66affSColin Finck _In_ ULONG OptionFlags)
271c2c66affSColin Finck {
272c2c66affSColin Finck UCHAR BlockData[16];
273c2c66affSColin Finck AES_KEY AesKey;
274c2c66affSColin Finck
275c2c66affSColin Finck /* Get they AES key */
276c2c66affSColin Finck KsecGetAesKey(&AesKey, OptionFlags);
277c2c66affSColin Finck
278c2c66affSColin Finck /* Do the AES decryption */
279c2c66affSColin Finck while (Length >= sizeof(BlockData))
280c2c66affSColin Finck {
281c2c66affSColin Finck aes_ecb_decrypt(Buffer, BlockData, &AesKey);
282c2c66affSColin Finck RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
283c2c66affSColin Finck Buffer = (PUCHAR)Buffer + sizeof(BlockData);
284c2c66affSColin Finck Length -= sizeof(BlockData);
285c2c66affSColin Finck }
286c2c66affSColin Finck
287c2c66affSColin Finck /* Erase the key data */
288c2c66affSColin Finck RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
289c2c66affSColin Finck }
290c2c66affSColin Finck
291c2c66affSColin Finck NTSTATUS
292c2c66affSColin Finck NTAPI
KsecEncryptMemory(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)293c2c66affSColin Finck KsecEncryptMemory (
294c2c66affSColin Finck _Inout_ PVOID Buffer,
295c2c66affSColin Finck _In_ ULONG Length,
296c2c66affSColin Finck _In_ ULONG OptionFlags)
297c2c66affSColin Finck {
298c2c66affSColin Finck /* Validate parameter */
299c2c66affSColin Finck if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
300c2c66affSColin Finck {
301c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
302c2c66affSColin Finck }
303c2c66affSColin Finck
304c2c66affSColin Finck /* Check if the length is not 16 bytes aligned */
305c2c66affSColin Finck if (Length & 15)
306c2c66affSColin Finck {
307c2c66affSColin Finck /* Is it at least 8 bytes aligned? */
308c2c66affSColin Finck if (Length & 7)
309c2c66affSColin Finck {
310c2c66affSColin Finck /* No, we can't deal with it! */
311c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
312c2c66affSColin Finck }
313c2c66affSColin Finck
314c2c66affSColin Finck /* Use triple DES encryption */
315c2c66affSColin Finck KsecEncryptMemoryDes3(Buffer, Length, OptionFlags);
316c2c66affSColin Finck }
317c2c66affSColin Finck else
318c2c66affSColin Finck {
319c2c66affSColin Finck /* Use AES encryption */
320c2c66affSColin Finck KsecEncryptMemoryAes(Buffer, Length, OptionFlags);
321c2c66affSColin Finck }
322c2c66affSColin Finck
323c2c66affSColin Finck return STATUS_SUCCESS;
324c2c66affSColin Finck }
325c2c66affSColin Finck
326c2c66affSColin Finck NTSTATUS
327c2c66affSColin Finck NTAPI
KsecDecryptMemory(_Inout_ PVOID Buffer,_In_ ULONG Length,_In_ ULONG OptionFlags)328c2c66affSColin Finck KsecDecryptMemory (
329c2c66affSColin Finck _Inout_ PVOID Buffer,
330c2c66affSColin Finck _In_ ULONG Length,
331c2c66affSColin Finck _In_ ULONG OptionFlags)
332c2c66affSColin Finck {
333c2c66affSColin Finck /* Validate parameter */
334c2c66affSColin Finck if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
335c2c66affSColin Finck {
336c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
337c2c66affSColin Finck }
338c2c66affSColin Finck
339c2c66affSColin Finck /* Check if the length is not 16 bytes aligned */
340c2c66affSColin Finck if (Length & 15)
341c2c66affSColin Finck {
342c2c66affSColin Finck /* Is it at least 8 bytes aligned? */
343c2c66affSColin Finck if (Length & 7)
344c2c66affSColin Finck {
345c2c66affSColin Finck /* No, we can't deal with it! */
346c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
347c2c66affSColin Finck }
348c2c66affSColin Finck
349c2c66affSColin Finck /* Use triple DES encryption */
350c2c66affSColin Finck KsecDecryptMemoryDes3(Buffer, Length, OptionFlags);
351c2c66affSColin Finck }
352c2c66affSColin Finck else
353c2c66affSColin Finck {
354c2c66affSColin Finck /* Use AES encryption */
355c2c66affSColin Finck KsecDecryptMemoryAes(Buffer, Length, OptionFlags);
356c2c66affSColin Finck }
357c2c66affSColin Finck
358c2c66affSColin Finck return STATUS_SUCCESS;
359c2c66affSColin Finck }
360