xref: /reactos/drivers/crypto/ksecdd/crypt.c (revision ab43f869)
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