ReactOS  0.4.15-dev-1377-ga59cecd
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 
17 typedef struct _KSEC_PROCESS_DATA
18 {
24 
25 typedef struct _KSEC_LOGON_DATA
26 {
29 
30 #if 0
31 void 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 
42 VOID
43 NTAPI
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 
74 static
75 VOID
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;
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 */
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;
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));
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 
137 static
138 VOID
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 
162 static
163 VOID
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 
187 static
188 VOID
191  _In_ ULONG Length,
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 
213 static
214 VOID
217  _In_ ULONG Length,
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 
239 static
240 VOID
243  _In_ ULONG Length,
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 
265 static
266 VOID
269  _In_ ULONG Length,
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 
291 NTSTATUS
292 NTAPI
295  _In_ ULONG Length,
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 
326 NTSTATUS
327 NTAPI
330  _In_ ULONG Length,
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 }
static VOID KsecGetKeyData(_Out_ UCHAR KeyData[32], _In_ ULONG OptionFlags)
Definition: crypt.c:76
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID WINAPI MD5Init(MD5_CTX *)
Definition: md5.c:45
static VOID KsecGetDes3Key(_Out_ PDES3_KEY Des3Key, _In_ ULONG OptionFlags)
Definition: crypt.c:139
#define DbgPrint
Definition: loader.c:25
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static VOID KsecGetAesKey(_Out_ PAES_KEY AesKey, _In_ ULONG OptionFlags)
Definition: crypt.c:164
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
static VOID KsecDecryptMemoryDes3(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:215
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
#define RTL_ENCRYPT_OPTION_CROSS_PROCESS
Definition: ksecdd.h:26
VOID WINAPI MD5Final(MD5_CTX *)
Definition: md5.c:113
void aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, aes_key *skey)
Definition: aes.c:1064
static VOID KsecEncryptMemoryAes(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:241
VOID WINAPI MD5Update(MD5_CTX *, const unsigned char *, unsigned int)
Definition: md5.c:59
uint32_t ULONG_PTR
Definition: typedefs.h:65
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:1747
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
struct _KSEC_PROCESS_DATA KSEC_PROCESS_DATA
void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const des3_key *des3)
Definition: des.c:1473
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define _Out_
Definition: no_sal2.h:160
Definition: bufpool.h:45
ULONG_PTR DirectoryTableBase
Definition: crypt.c:22
int64_t LONGLONG
Definition: typedefs.h:68
LONGLONG CreateTime
Definition: crypt.c:21
VOID NTAPI KsecInitializeEncryptionSupport(VOID)
Definition: crypt.c:44
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
unsigned char digest[16]
Definition: msi.c:4083
struct _KSEC_LOGON_DATA KSEC_LOGON_DATA
HANDLE ProcessId
Definition: crypt.c:20
#define _Inout_
Definition: no_sal2.h:162
#define RTL_ENCRYPT_OPTION_SAME_PROCESS
Definition: ksecdd.h:25
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _KSEC_LOGON_DATA * PKSEC_LOGON_DATA
#define RTL_ENCRYPT_OPTION_SAME_LOGON
Definition: ksecdd.h:27
#define NOTHING
Definition: env_spec_w32.h:461
DES3_KEY KsecGlobalDes3Key
Definition: crypt.c:14
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const des3_key *des3)
Definition: des.c:1485
LONGLONG NTAPI PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
Definition: process.c:1023
#define _In_
Definition: no_sal2.h:158
void aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, aes_key *skey)
Definition: aes.c:1165
PEPROCESS Process
Definition: crypt.c:19
LUID LogonId
Definition: crypt.c:27
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
NTSTATUS NTAPI KsecEncryptMemory(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:293
static VOID KsecDecryptMemoryAes(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:267
struct _KSEC_PROCESS_DATA * PKSEC_PROCESS_DATA
VOID NTAPI PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
Definition: security.c:861
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
AES_KEY KsecGlobalAesKey
Definition: crypt.c:15
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: msi.c:4078
MD5_CTX KsecLoadTimeStartMd5s[2]
Definition: crypt.c:13
NTSTATUS NTAPI KsecGatherEntropyData(PKSEC_ENTROPY_DATA EntropyData)
Definition: random.c:92
static VOID KsecEncryptMemoryDes3(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:189
FORCEINLINE PVOID RtlSecureZeroMemory(_Out_writes_bytes_all_(Size) PVOID Pointer, _In_ SIZE_T Size)
Definition: rtlfuncs.h:3127
int aes_setup(const unsigned char *key, int keylen, int rounds, aes_key *skey)
Definition: aes.c:937
int des3_setup(const unsigned char *key, int keylen, int num_rounds, des3_key *des3)
Definition: des.c:1432
NTSTATUS NTAPI KsecDecryptMemory(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:328