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