ReactOS 0.4.17-dev-116-ga4b6fe9
crypt.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel Security Support Provider Interface Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Encryption and decryption support for ksecdd
5 * COPYRIGHT: Copyright 2014-2020 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "ksecdd.h"
11
15
16typedef struct _KSEC_PROCESS_DATA
17{
23
24typedef struct _KSEC_LOGON_DATA
25{
28
29#if 0
30void PrintKeyData(PUCHAR KeyData)
31{
32 ULONG i;
33 for (i = 0; i < 32; i++)
34 {
35 DbgPrint("%02X", KeyData[i]);
36 }
37 DbgPrint("\n");
38}
39#endif
40
41VOID
44 VOID)
45{
46 KSEC_ENTROPY_DATA EntropyData;
47 MD5_CTX Md5Context;
48 UCHAR KeyDataBuffer[32];
49
50 KsecGatherEntropyData(&EntropyData);
51 MD5Init(&Md5Context);
52 MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
53 KsecLoadTimeStartMd5s[0] = Md5Context;
54 MD5Final(&Md5Context);
55 RtlCopyMemory(KeyDataBuffer, &Md5Context.digest, 16);
56
57 KsecGatherEntropyData(&EntropyData);
58 Md5Context = KsecLoadTimeStartMd5s[0];
59 MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
60 KsecLoadTimeStartMd5s[1] = Md5Context;
61 MD5Final(&Md5Context);
62 RtlCopyMemory(&KeyDataBuffer[16], &Md5Context.digest, 16);
63
64 /* Create the global keys */
65 aes_setup(KeyDataBuffer, 32, 0, &KsecGlobalAesKey);
66 des3_setup(KeyDataBuffer, 24, 0, &KsecGlobalDes3Key);
67
68 /* Erase the temp data */
69 RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
70 RtlSecureZeroMemory(&Md5Context, sizeof(Md5Context));
71}
72
73static
74VOID
76 _Out_ UCHAR KeyData[32],
77 _In_ ULONG OptionFlags)
78{
79 MD5_CTX Md5Contexts[2];
80 KSEC_PROCESS_DATA ProcessData;
81 KSEC_LOGON_DATA LogonData;
82 PEPROCESS CurrentProcess;
84
85 /* We need to generate the key, start with our load MD5s */
86 Md5Contexts[0] = KsecLoadTimeStartMd5s[0];
87 Md5Contexts[1] = KsecLoadTimeStartMd5s[1];
88
89 /* Get the current process */
90 CurrentProcess = PsGetCurrentProcess();
91
92 if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
93 {
94 /* Hash some process specific data to generate the key */
95 RtlZeroMemory(&ProcessData, sizeof(ProcessData));
96 ProcessData.Process = CurrentProcess;
97 ProcessData.ProcessId = CurrentProcess->UniqueProcessId;
98 ProcessData.CreateTime = PsGetProcessCreateTimeQuadPart(CurrentProcess);
99 ProcessData.DirectoryTableBase = CurrentProcess->Pcb.DirectoryTableBase[0];
100 MD5Update(&Md5Contexts[0], (PVOID)&ProcessData, sizeof(ProcessData));
101 MD5Update(&Md5Contexts[1], (PVOID)&ProcessData, sizeof(ProcessData));
102 }
103 else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
104 {
105 /* Hash the logon id to generate the key */
106 RtlZeroMemory(&LogonData, sizeof(LogonData));
107 Token = PsReferencePrimaryToken(CurrentProcess);
110 MD5Update(&Md5Contexts[0], (PVOID)&LogonData, sizeof(LogonData));
111 MD5Update(&Md5Contexts[1], (PVOID)&LogonData, sizeof(LogonData));
112 }
113 else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
114 {
115 /* Use the original MD5s to generate the global key */
116 NOTHING;
117 }
118 else
119 {
120 /* Must not pass anything else */
121 ASSERT(FALSE);
122 }
123
124 /* Finalize the MD5s */
125 MD5Final(&Md5Contexts[0]);
126 MD5Final(&Md5Contexts[1]);
127
128 /* Copy the md5 data */
129 RtlCopyMemory(KeyData, &Md5Contexts[0].digest, 16);
130 RtlCopyMemory((PUCHAR)KeyData + 16, &Md5Contexts[1].digest, 16);
131
132 /* Erase the temp data */
133 RtlSecureZeroMemory(&Md5Contexts, sizeof(Md5Contexts));
134}
135
136static
137VOID
139 _Out_ PDES3_KEY Des3Key,
140 _In_ ULONG OptionFlags)
141{
142 UCHAR KeyDataBuffer[32];
143
144 /* Check if the caller allows cross process encryption */
145 if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
146 {
147 /* Return our global cached DES3 key */
148 *Des3Key = KsecGlobalDes3Key;
149 }
150 else
151 {
152 /* Setup the key */
153 KsecGetKeyData(KeyDataBuffer, OptionFlags);
154 des3_setup(KeyDataBuffer, 24, 0, Des3Key);
155
156 /* Erase the temp data */
157 RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
158 }
159}
160
161static
162VOID
164 _Out_ PAES_KEY AesKey,
165 _In_ ULONG OptionFlags)
166{
167 UCHAR KeyDataBuffer[32];
168
169 /* Check if the caller allows cross process encryption */
170 if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
171 {
172 /* Return our global cached AES key */
173 *AesKey = KsecGlobalAesKey;
174 }
175 else
176 {
177 /* Setup the key */
178 KsecGetKeyData(KeyDataBuffer, OptionFlags);
179 aes_setup(KeyDataBuffer, 32, 0, AesKey);
180
181 /* Erase the temp data */
182 RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
183 }
184}
185
186static
187VOID
191 _In_ ULONG OptionFlags)
192{
193 UCHAR EncryptedBlockData[8];
194 DES3_KEY Des3Key;
195
196 /* Get they triple DES key */
197 KsecGetDes3Key(&Des3Key, OptionFlags);
198
199 /* Do the triple DES encryption */
200 while (Length >= sizeof(EncryptedBlockData))
201 {
202 des3_ecb_encrypt(Buffer, EncryptedBlockData, &Des3Key);
203 RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
204 Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
205 Length -= sizeof(EncryptedBlockData);
206 }
207
208 /* Erase the key data */
209 RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));
210}
211
212static
213VOID
217 _In_ ULONG OptionFlags)
218{
219 UCHAR BlockData[8];
220 DES3_KEY Des3Key;
221
222 /* Get they triple DES key */
223 KsecGetDes3Key(&Des3Key, OptionFlags);
224
225 /* Do the triple DES decryption */
226 while (Length >= sizeof(BlockData))
227 {
228 des3_ecb_decrypt(Buffer, BlockData, &Des3Key);
229 RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
230 Buffer = (PUCHAR)Buffer + sizeof(BlockData);
231 Length -= sizeof(BlockData);
232 }
233
234 /* Erase the key data */
235 RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));
236}
237
238static
239VOID
243 _In_ ULONG OptionFlags)
244{
245 UCHAR EncryptedBlockData[16];
246 AES_KEY AesKey;
247
248 /* Get they AES key */
249 KsecGetAesKey(&AesKey, OptionFlags);
250
251 /* Do the AES encryption */
252 while (Length >= sizeof(EncryptedBlockData))
253 {
254 aes_ecb_encrypt(Buffer, EncryptedBlockData, &AesKey);
255 RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
256 Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
257 Length -= sizeof(EncryptedBlockData);
258 }
259
260 /* Erase the key data */
261 RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
262}
263
264static
265VOID
269 _In_ ULONG OptionFlags)
270{
271 UCHAR BlockData[16];
272 AES_KEY AesKey;
273
274 /* Get they AES key */
275 KsecGetAesKey(&AesKey, OptionFlags);
276
277 /* Do the AES decryption */
278 while (Length >= sizeof(BlockData))
279 {
280 aes_ecb_decrypt(Buffer, BlockData, &AesKey);
281 RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
282 Buffer = (PUCHAR)Buffer + sizeof(BlockData);
283 Length -= sizeof(BlockData);
284 }
285
286 /* Erase the key data */
287 RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
288}
289
291NTAPI
295 _In_ ULONG OptionFlags)
296{
297 /* Validate parameter */
298 if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
299 {
301 }
302
303 /* Check if the length is not 16 bytes aligned */
304 if (Length & 15)
305 {
306 /* Is it at least 8 bytes aligned? */
307 if (Length & 7)
308 {
309 /* No, we can't deal with it! */
311 }
312
313 /* Use triple DES encryption */
314 KsecEncryptMemoryDes3(Buffer, Length, OptionFlags);
315 }
316 else
317 {
318 /* Use AES encryption */
319 KsecEncryptMemoryAes(Buffer, Length, OptionFlags);
320 }
321
322 return STATUS_SUCCESS;
323}
324
326NTAPI
330 _In_ ULONG OptionFlags)
331{
332 /* Validate parameter */
333 if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
334 {
336 }
337
338 /* Check if the length is not 16 bytes aligned */
339 if (Length & 15)
340 {
341 /* Is it at least 8 bytes aligned? */
342 if (Length & 7)
343 {
344 /* No, we can't deal with it! */
346 }
347
348 /* Use triple DES encryption */
349 KsecDecryptMemoryDes3(Buffer, Length, OptionFlags);
350 }
351 else
352 {
353 /* Use AES encryption */
354 KsecDecryptMemoryAes(Buffer, Length, OptionFlags);
355 }
356
357 return STATUS_SUCCESS;
358}
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
#define FALSE
Definition: types.h:117
void WINAPI MD5Update(struct md5_ctx *, const unsigned char *, unsigned int)
void WINAPI MD5Init(struct md5_ctx *)
void WINAPI MD5Final(struct md5_ctx *)
void aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, aes_key *skey)
Definition: aes.c:1064
void aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, aes_key *skey)
Definition: aes.c:1165
int aes_setup(const unsigned char *key, int keylen, int rounds, aes_key *skey)
Definition: aes.c:937
void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const des3_key *des3)
Definition: des.c:1473
void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const des3_key *des3)
Definition: des.c:1485
int des3_setup(const unsigned char *key, int keylen, int num_rounds, des3_key *des3)
Definition: des.c:1432
struct _KSEC_PROCESS_DATA KSEC_PROCESS_DATA
AES_KEY KsecGlobalAesKey
Definition: crypt.c:14
static VOID KsecEncryptMemoryDes3(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:188
static VOID KsecGetDes3Key(_Out_ PDES3_KEY Des3Key, _In_ ULONG OptionFlags)
Definition: crypt.c:138
static VOID KsecGetAesKey(_Out_ PAES_KEY AesKey, _In_ ULONG OptionFlags)
Definition: crypt.c:163
static VOID KsecEncryptMemoryAes(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:240
DES3_KEY KsecGlobalDes3Key
Definition: crypt.c:13
struct _KSEC_LOGON_DATA * PKSEC_LOGON_DATA
MD5_CTX KsecLoadTimeStartMd5s[2]
Definition: crypt.c:12
NTSTATUS NTAPI KsecDecryptMemory(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:327
static VOID KsecGetKeyData(_Out_ UCHAR KeyData[32], _In_ ULONG OptionFlags)
Definition: crypt.c:75
static VOID KsecDecryptMemoryAes(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:266
static VOID KsecDecryptMemoryDes3(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:214
VOID NTAPI KsecInitializeEncryptionSupport(VOID)
Definition: crypt.c:43
struct _KSEC_LOGON_DATA KSEC_LOGON_DATA
NTSTATUS NTAPI KsecEncryptMemory(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:292
struct _KSEC_PROCESS_DATA * PKSEC_PROCESS_DATA
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
#define NOTHING
Definition: input_list.c:10
#define RTL_ENCRYPT_OPTION_SAME_LOGON
Definition: ksecdd.h:27
NTSTATUS NTAPI KsecGatherEntropyData(PKSEC_ENTROPY_DATA EntropyData)
Definition: random.c:91
#define RTL_ENCRYPT_OPTION_SAME_PROCESS
Definition: ksecdd.h:25
#define RTL_ENCRYPT_OPTION_CROSS_PROCESS
Definition: ksecdd.h:26
#define ASSERT(a)
Definition: mode.c:44
#define PsDereferencePrimaryToken(T)
Definition: imports.h:301
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
LONGLONG NTAPI PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
Definition: process.c:1023
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
NTSTATUS NTAPI SeQueryAuthenticationIdToken(_In_ PACCESS_TOKEN Token, _Out_ PLUID LogonId)
Queries the authentication ID of an access token.
Definition: token.c:2037
#define STATUS_SUCCESS
Definition: shellext.h:65
unsigned char digest[16]
Definition: hmac_md5.h:32
KPROCESS Pcb
Definition: pstypes.h:1351
HANDLE UniqueProcessId
Definition: pstypes.h:1356
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2215
LUID LogonId
Definition: crypt.c:26
ULONG_PTR DirectoryTableBase
Definition: crypt.c:21
HANDLE ProcessId
Definition: crypt.c:19
PEPROCESS Process
Definition: crypt.c:18
LONGLONG CreateTime
Definition: crypt.c:20
unsigned char UCHAR
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define PsGetCurrentProcess
Definition: psfuncs.h:17
FORCEINLINE PVOID RtlSecureZeroMemory(_Out_writes_bytes_all_(Size) PVOID Pointer, _In_ SIZE_T Size)
Definition: rtlfuncs.h:3142