ReactOS  0.4.13-dev-982-g9853eab
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 VOID
31 NTAPI
33  VOID)
34 {
35  KSEC_ENTROPY_DATA EntropyData;
36  MD5_CTX Md5Context;
37  UCHAR KeyDataBuffer[32];
38 
39  KsecGatherEntropyData(&EntropyData);
40  MD5Init(&Md5Context);
41  MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
42  KsecLoadTimeStartMd5s[0] = Md5Context;
43  MD5Final(&Md5Context);
44  RtlCopyMemory(KeyDataBuffer, &Md5Context.digest, 16);
45 
46  KsecGatherEntropyData(&EntropyData);
47  Md5Context = KsecLoadTimeStartMd5s[0];
48  MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData));
49  KsecLoadTimeStartMd5s[1] = Md5Context;
50  MD5Final(&Md5Context);
51  RtlCopyMemory(&KeyDataBuffer[16], &Md5Context.digest, 16);
52 
53  /* Create the global keys */
54  aes_setup(KeyDataBuffer, 32, 0, &KsecGlobalAesKey);
55  des3_setup(KeyDataBuffer, 24, 0, &KsecGlobalDes3Key);
56 
57  /* Erase the temp data */
58  RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
59  RtlSecureZeroMemory(&Md5Context, sizeof(Md5Context));
60 }
61 
62 static
63 VOID
65  _Out_ UCHAR KeyData[32],
66  _In_ ULONG OptionFlags)
67 {
68  MD5_CTX Md5Contexts[2];
69  KSEC_PROCESS_DATA ProcessData;
70  KSEC_LOGON_DATA LogonData;
73 
74  /* We need to generate the key, start with our load MD5s */
75  Md5Contexts[0] = KsecLoadTimeStartMd5s[0];
76  Md5Contexts[1] = KsecLoadTimeStartMd5s[1];
77 
78  /* Get the current process */
80 
81  if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
82  {
83  ProcessData.Process = CurrentProcess;
84  ProcessData.ProcessId = CurrentProcess->UniqueProcessId;
86  ProcessData.DirectoryTableBase = CurrentProcess->Pcb.DirectoryTableBase[0];
87  MD5Update(&Md5Contexts[0], (PVOID)&ProcessData, sizeof(ProcessData));
88  MD5Update(&Md5Contexts[1], (PVOID)&ProcessData, sizeof(ProcessData));
89  }
90  else // if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
91  {
95  MD5Update(&Md5Contexts[0], (PVOID)&LogonData, sizeof(LogonData));
96  MD5Update(&Md5Contexts[1], (PVOID)&LogonData, sizeof(LogonData));
97  }
98 
99  /* Finalize the MD5s */
100  MD5Final(&Md5Contexts[0]);
101  MD5Final(&Md5Contexts[1]);
102 
103  /* Copy the md5 data */
104  RtlCopyMemory(KeyData, &Md5Contexts[0].digest, 16);
105  RtlCopyMemory((PUCHAR)KeyData + 16, &Md5Contexts[1].digest, 16);
106 
107  /* Erase the temp data */
108  RtlSecureZeroMemory(&Md5Contexts, sizeof(Md5Contexts));
109 }
110 
111 static
112 VOID
114  _Out_ PDES3_KEY Des3Key,
115  _In_ ULONG OptionFlags)
116 {
117  UCHAR KeyDataBuffer[32];
118 
119  /* Check if the caller allows cross process encryption */
120  if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
121  {
122  /* Return our global cached DES3 key */
123  *Des3Key = KsecGlobalDes3Key;
124  }
125  else
126  {
127  /* Setup the key */
128  KsecGetKeyData(KeyDataBuffer, OptionFlags);
129  des3_setup(KeyDataBuffer, 24, 0, Des3Key);
130 
131  /* Erase the temp data */
132  RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
133  }
134 }
135 
136 static
137 VOID
139  _Out_ PAES_KEY AesKey,
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 AES key */
148  *AesKey = KsecGlobalAesKey;
149  }
150  else
151  {
152  /* Setup the key */
153  KsecGetKeyData(KeyDataBuffer, OptionFlags);
154  aes_setup(KeyDataBuffer, 32, 0, AesKey);
155 
156  /* Erase the temp data */
157  RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer));
158  }
159 }
160 
161 static
162 VOID
165  _In_ ULONG Length,
166  _In_ ULONG OptionFlags)
167 {
168  UCHAR EncryptedBlockData[8];
169  DES3_KEY Des3Key;
170 
171  /* Get they triple DES key */
172  KsecGetDes3Key(&Des3Key, OptionFlags);
173 
174  /* Do the triple DES encryption */
175  while (Length >= sizeof(EncryptedBlockData))
176  {
177  des3_ecb_encrypt(Buffer, EncryptedBlockData, &Des3Key);
178  RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
179  Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
180  Length -= sizeof(EncryptedBlockData);
181  }
182 
183  /* Erase the key data */
184  RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));
185 }
186 
187 static
188 VOID
191  _In_ ULONG Length,
192  _In_ ULONG OptionFlags)
193 {
194  UCHAR BlockData[8];
195  DES3_KEY Des3Key;
196 
197  /* Get they triple DES key */
198  KsecGetDes3Key(&Des3Key, OptionFlags);
199 
200  /* Do the triple DES decryption */
201  while (Length >= sizeof(BlockData))
202  {
203  des3_ecb_decrypt(Buffer, BlockData, &Des3Key);
204  RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
205  Buffer = (PUCHAR)Buffer + sizeof(BlockData);
206  Length -= sizeof(BlockData);
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 EncryptedBlockData[16];
221  AES_KEY AesKey;
222 
223  /* Get they AES key */
224  KsecGetAesKey(&AesKey, OptionFlags);
225 
226  /* Do the AES encryption */
227  while (Length >= sizeof(EncryptedBlockData))
228  {
229  aes_ecb_encrypt(Buffer, EncryptedBlockData, &AesKey);
230  RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData));
231  Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData);
232  Length -= sizeof(EncryptedBlockData);
233  }
234 
235  /* Erase the key data */
236  RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
237 }
238 
239 static
240 VOID
243  _In_ ULONG Length,
244  _In_ ULONG OptionFlags)
245 {
246  UCHAR BlockData[16];
247  AES_KEY AesKey;
248 
249  /* Get they AES key */
250  KsecGetAesKey(&AesKey, OptionFlags);
251 
252  /* Do the AES decryption */
253  while (Length >= sizeof(BlockData))
254  {
255  aes_ecb_decrypt(Buffer, BlockData, &AesKey);
256  RtlCopyMemory(Buffer, BlockData, sizeof(BlockData));
257  Buffer = (PUCHAR)Buffer + sizeof(BlockData);
258  Length -= sizeof(BlockData);
259  }
260 
261  /* Erase the key data */
262  RtlSecureZeroMemory(&AesKey, sizeof(AesKey));
263 }
264 
265 NTSTATUS
266 NTAPI
269  _In_ ULONG Length,
270  _In_ ULONG OptionFlags)
271 {
272  /* Validate parameter */
273  if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
274  {
276  }
277 
278  /* Check if the length is not 16 bytes aligned */
279  if (Length & 15)
280  {
281  /* Is it at least 8 bytes aligned? */
282  if (Length & 7)
283  {
284  /* No, we can't deal with it! */
286  }
287 
288  /* Use triple DES encryption */
289  KsecEncryptMemoryDes3(Buffer, Length, OptionFlags);
290  }
291  else
292  {
293  /* Use AES encryption */
294  KsecEncryptMemoryAes(Buffer, Length, OptionFlags);
295  }
296 
297  return STATUS_SUCCESS;
298 }
299 
300 NTSTATUS
301 NTAPI
304  _In_ ULONG Length,
305  _In_ ULONG OptionFlags)
306 {
307  /* Validate parameter */
308  if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON)
309  {
311  }
312 
313  /* Check if the length is not 16 bytes aligned */
314  if (Length & 15)
315  {
316  /* Is it at least 8 bytes aligned? */
317  if (Length & 7)
318  {
319  /* No, we can't deal with it! */
321  }
322 
323  /* Use triple DES encryption */
324  KsecDecryptMemoryDes3(Buffer, Length, OptionFlags);
325  }
326  else
327  {
328  /* Use AES encryption */
329  KsecDecryptMemoryAes(Buffer, Length, OptionFlags);
330  }
331 
332  return STATUS_SUCCESS;
333 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static VOID KsecGetKeyData(_Out_ UCHAR KeyData[32], _In_ ULONG OptionFlags)
Definition: crypt.c:64
VOID WINAPI MD5Init(MD5_CTX *)
Definition: md5.c:45
static VOID KsecGetDes3Key(_Out_ PDES3_KEY Des3Key, _In_ ULONG OptionFlags)
Definition: crypt.c:113
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static VOID KsecGetAesKey(_Out_ PAES_KEY AesKey, _In_ ULONG OptionFlags)
Definition: crypt.c:138
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:189
_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:215
VOID WINAPI MD5Update(MD5_CTX *, const unsigned char *, unsigned int)
Definition: md5.c:59
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:1752
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp: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:323
Definition: bufpool.h:45
ULONG_PTR DirectoryTableBase
Definition: crypt.c:22
int64_t LONGLONG
Definition: typedefs.h:66
LONGLONG CreateTime
Definition: crypt.c:21
VOID NTAPI KsecInitializeEncryptionSupport(VOID)
Definition: crypt.c:32
ULONG CurrentProcess
Definition: shell.c:125
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:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#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
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:204
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
NTSTATUS NTAPI KsecEncryptMemory(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:267
static VOID KsecDecryptMemoryAes(_Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags)
Definition: crypt.c:241
struct _KSEC_PROCESS_DATA * PKSEC_PROCESS_DATA
VOID NTAPI PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
Definition: security.c:835
unsigned int ULONG
Definition: retypes.h:1
AES_KEY KsecGlobalAesKey
Definition: crypt.c:15
Definition: msi.c:4078
MD5_CTX KsecLoadTimeStartMd5s[2]
Definition: crypt.c:13
return STATUS_SUCCESS
Definition: btrfs.c:2777
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:163
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:302