xref: /reactos/dll/win32/advapi32/misc/sysfunc.c (revision 4114dcad)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/advapi32/misc/sysfunc.c
5  * PURPOSE:         advapi32.dll system functions (undocumented)
6  * PROGRAMMER:      Emanuele Aliberti
7  * UPDATE HISTORY:
8  *  19990413 EA created
9  *  19990415 EA
10  *  20080424 Ported from WINE
11  */
12 
13 #include <advapi32.h>
14 #include <ntsecapi.h>
15 #include <ksecioctl.h>
16 #include <md4.h>
17 #include <md5.h>
18 #include <rc4.h>
19 
20 static const unsigned char CRYPT_LMhash_Magic[8] =
21     { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
22 static const unsigned char DefaultSessionKey[16] =
23     {'D', 'e', 'f', 'S', 'e', 's', 's', 'i', 'o', 'n', 'K', 'e', 'y', '!', '@', '#'};
24 
25 /******************************************************************************
26  * SystemFunction001  [ADVAPI32.@]
27  *
28  * Encrypts a single block of data using DES
29  *
30  * PARAMS
31  *   data    [I] data to encrypt    (8 bytes)
32  *   key     [I] key data           (7 bytes)
33  *   output  [O] the encrypted data (8 bytes)
34  *
35  * RETURNS
36  *  Success: STATUS_SUCCESS
37  *  Failure: STATUS_UNSUCCESSFUL
38  *
39  */
40 NTSTATUS
SystemFunction001(const BYTE * data,const BYTE * key,LPBYTE output)41 WINAPI SystemFunction001(const BYTE *data, const BYTE *key, LPBYTE output)
42 {
43     if (!data || !output)
44         return STATUS_UNSUCCESSFUL;
45     CRYPT_DEShash(output, key, data);
46     return STATUS_SUCCESS;
47 }
48 
49 
50 /******************************************************************************
51  * SystemFunction002  [ADVAPI32.@]
52  *
53  * Decrypts a single block of data using DES
54  *
55  * PARAMS
56  *   data    [I] data to decrypt    (8 bytes)
57  *   key     [I] key data           (7 bytes)
58  *   output  [O] the decrypted data (8 bytes)
59  *
60  * RETURNS
61  *  Success: STATUS_SUCCESS
62  *  Failure: STATUS_UNSUCCESSFUL
63  *
64  */
65 NTSTATUS
SystemFunction002(const BYTE * data,const BYTE * key,LPBYTE output)66 WINAPI SystemFunction002(const BYTE *data, const BYTE *key, LPBYTE output)
67 {
68     if (!data || !output)
69         return STATUS_UNSUCCESSFUL;
70     CRYPT_DESunhash(output, key, data);
71     return STATUS_SUCCESS;
72 }
73 
74 
75 /******************************************************************************
76  * SystemFunction003  [ADVAPI32.@]
77  *
78  * Hashes a key using DES and a fixed datablock
79  *
80  * PARAMS
81  *   key     [I] key data    (7 bytes)
82  *   output  [O] hashed key  (8 bytes)
83  *
84  * RETURNS
85  *  Success: STATUS_SUCCESS
86  *  Failure: STATUS_UNSUCCESSFUL
87  *
88  */
89 NTSTATUS
SystemFunction003(const BYTE * key,LPBYTE output)90 WINAPI SystemFunction003(const BYTE *key, LPBYTE output)
91 {
92     if (!output)
93         return STATUS_UNSUCCESSFUL;
94     CRYPT_DEShash(output, key, CRYPT_LMhash_Magic);
95     return STATUS_SUCCESS;
96 }
97 
98 
99 /******************************************************************************
100  * SystemFunction004  [ADVAPI32.@]
101  *
102  * Encrypts a block of data with DES in ECB mode, preserving the length
103  *
104  * PARAMS
105  *   data    [I] data to encrypt
106  *   key     [I] key data (up to 7 bytes)
107  *   output  [O] buffer to receive encrypted data
108  *
109  * RETURNS
110  *  Success: STATUS_SUCCESS
111  *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
112  *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
113  *
114  * NOTES
115  *  Encrypt buffer size should be input size rounded up to 8 bytes
116  *   plus an extra 8 bytes.
117  */
118 NTSTATUS
SystemFunction004(const struct ustring * in,const struct ustring * key,struct ustring * out)119 WINAPI SystemFunction004(const struct ustring *in,
120                                   const struct ustring *key,
121                                   struct ustring *out)
122 {
123     union {
124         unsigned char uc[8];
125           unsigned int  ui[2];
126     } data;
127     unsigned char deskey[7];
128     unsigned int crypt_len, ofs;
129 
130     if (key->Length<=0)
131         return STATUS_INVALID_PARAMETER_2;
132 
133     crypt_len = ((in->Length+7)&~7);
134     if (out->MaximumLength < (crypt_len+8))
135     {
136         out->Length = crypt_len + 8;
137         return STATUS_BUFFER_TOO_SMALL;
138     }
139 
140     data.ui[0] = in->Length;
141     data.ui[1] = 1;
142 
143     if (key->Length<sizeof deskey)
144     {
145         memset(deskey, 0, sizeof deskey);
146         memcpy(deskey, key->Buffer, key->Length);
147     }
148     else
149         memcpy(deskey, key->Buffer, sizeof deskey);
150 
151     CRYPT_DEShash(out->Buffer, deskey, data.uc);
152 
153     for(ofs=0; ofs<(crypt_len-8); ofs+=8)
154         CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs);
155 
156     memset(data.uc, 0, sizeof data.uc);
157     memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len);
158     CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc);
159 
160     out->Length = crypt_len+8;
161 
162     return STATUS_SUCCESS;
163 }
164 
165 /******************************************************************************
166  * SystemFunction005  [ADVAPI32.@]
167  *
168  * Decrypts a block of data with DES in ECB mode
169  *
170  * PARAMS
171  *   data    [I] data to decrypt
172  *   key     [I] key data (up to 7 bytes)
173  *   output  [O] buffer to receive decrypted data
174  *
175  * RETURNS
176  *  Success: STATUS_SUCCESS
177  *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
178  *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
179  *
180  */
181 NTSTATUS
SystemFunction005(const struct ustring * in,const struct ustring * key,struct ustring * out)182 WINAPI SystemFunction005(const struct ustring *in,
183                          const struct ustring *key,
184                          struct ustring *out)
185 {
186     union {
187         unsigned char uc[8];
188         unsigned int  ui[2];
189     } data;
190     unsigned char deskey[7];
191     unsigned int ofs, crypt_len;
192 
193     if (key->Length<=0)
194         return STATUS_INVALID_PARAMETER_2;
195 
196     if (key->Length<sizeof deskey)
197     {
198         memset(deskey, 0, sizeof deskey);
199         memcpy(deskey, key->Buffer, key->Length);
200     }
201     else
202         memcpy(deskey, key->Buffer, sizeof deskey);
203 
204     CRYPT_DESunhash(data.uc, deskey, in->Buffer);
205 
206     if (data.ui[1] != 1)
207         return STATUS_UNKNOWN_REVISION;
208 
209     crypt_len = data.ui[0];
210     if (crypt_len > out->MaximumLength)
211     {
212         out->Length = crypt_len;
213         return STATUS_BUFFER_TOO_SMALL;
214     }
215 
216     for (ofs=0; (ofs+8)<crypt_len; ofs+=8)
217         CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8);
218 
219     if (ofs<crypt_len)
220     {
221         CRYPT_DESunhash(data.uc, deskey, in->Buffer+ofs+8);
222         memcpy(out->Buffer+ofs, data.uc, crypt_len-ofs);
223     }
224 
225     out->Length = crypt_len;
226 
227     return STATUS_SUCCESS;
228 }
229 
230 /******************************************************************************
231  * SystemFunction007  [ADVAPI32.@]
232  *
233  * MD4 hash a unicode string
234  *
235  * PARAMS
236  *   string  [I] the string to hash
237  *   output  [O] the md4 hash of the string (16 bytes)
238  *
239  * RETURNS
240  *  Success: STATUS_SUCCESS
241  *  Failure: STATUS_UNSUCCESSFUL
242  *
243  */
244 NTSTATUS
SystemFunction007(const UNICODE_STRING * string,LPBYTE hash)245 WINAPI SystemFunction007(const UNICODE_STRING *string, LPBYTE hash)
246 {
247     MD4_CTX ctx;
248 
249     MD4Init( &ctx );
250     MD4Update( &ctx, (const BYTE *)string->Buffer, string->Length );
251     MD4Final( &ctx );
252     memcpy( hash, ctx.digest, 0x10 );
253 
254     return STATUS_SUCCESS;
255 }
256 
257 /******************************************************************************
258  * SystemFunction008  [ADVAPI32.@]
259  *
260  * Creates a LM response from a challenge and a password hash
261  *
262  * PARAMS
263  *   challenge  [I] Challenge from authentication server
264  *   hash       [I] NTLM hash (from SystemFunction006)
265  *   response   [O] response to send back to the server
266  *
267  * RETURNS
268  *  Success: STATUS_SUCCESS
269  *  Failure: STATUS_UNSUCCESSFUL
270  *
271  * NOTES
272  *  see http://davenport.sourceforge.net/ntlm.html#theLmResponse
273  *
274  */
275 NTSTATUS
SystemFunction008(const BYTE * challenge,const BYTE * hash,LPBYTE response)276 WINAPI SystemFunction008(const BYTE *challenge, const BYTE *hash, LPBYTE response)
277 {
278     BYTE key[7*3];
279 
280     if (!challenge || !response)
281         return STATUS_UNSUCCESSFUL;
282 
283     memset(key, 0, sizeof key);
284     memcpy(key, hash, 0x10);
285 
286     CRYPT_DEShash(response, key, challenge);
287     CRYPT_DEShash(response+8, key+7, challenge);
288     CRYPT_DEShash(response+16, key+14, challenge);
289 
290     return STATUS_SUCCESS;
291 }
292 
293 /******************************************************************************
294  * SystemFunction009  [ADVAPI32.@]
295  *
296  * Seems to do the same as SystemFunction008...
297  */
298 NTSTATUS
SystemFunction009(const BYTE * challenge,const BYTE * hash,LPBYTE response)299 WINAPI SystemFunction009(const BYTE *challenge, const BYTE *hash, LPBYTE response)
300 {
301     return SystemFunction008(challenge, hash, response);
302 }
303 
304 /******************************************************************************
305  * SystemFunction010  [ADVAPI32.@]
306  * SystemFunction011  [ADVAPI32.@]
307  *
308  * MD4 hashes 16 bytes of data
309  *
310  * PARAMS
311  *   unknown []  seems to have no effect on the output
312  *   data    [I] pointer to data to hash (16 bytes)
313  *   output  [O] the md4 hash of the data (16 bytes)
314  *
315  * RETURNS
316  *  Success: STATUS_SUCCESS
317  *  Failure: STATUS_UNSUCCESSFUL
318  *
319  */
320 NTSTATUS
SystemFunction010(LPVOID unknown,const BYTE * data,LPBYTE hash)321 WINAPI SystemFunction010(LPVOID unknown, const BYTE *data, LPBYTE hash)
322 {
323     MD4_CTX ctx;
324 
325     MD4Init( &ctx );
326     MD4Update( &ctx, data, 0x10 );
327     MD4Final( &ctx );
328     memcpy( hash, ctx.digest, 0x10 );
329 
330     return STATUS_SUCCESS;
331 }
332 
333 /******************************************************************************
334  * SystemFunction012  [ADVAPI32.@]
335  * SystemFunction014  [ADVAPI32.@]
336  * SystemFunction016  [ADVAPI32.@]
337  * SystemFunction018  [ADVAPI32.@]
338  * SystemFunction020  [ADVAPI32.@]
339  * SystemFunction022  [ADVAPI32.@]
340  *
341  * Encrypts two DES blocks with two keys
342  *
343  * PARAMS
344  *   data    [I] data to encrypt (16 bytes)
345  *   key     [I] key data (two lots of 7 bytes)
346  *   output  [O] buffer to receive encrypted data (16 bytes)
347  *
348  * RETURNS
349  *  Success: STATUS_SUCCESS
350  *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
351  */
352 NTSTATUS
SystemFunction012(const BYTE * in,const BYTE * key,LPBYTE out)353 WINAPI SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out)
354 {
355     if (!in || !out)
356         return STATUS_UNSUCCESSFUL;
357 
358     CRYPT_DEShash(out, key, in);
359     CRYPT_DEShash(out+8, key+7, in+8);
360     return STATUS_SUCCESS;
361 }
362 
363 /******************************************************************************
364  * SystemFunction013  [ADVAPI32.@]
365  * SystemFunction015  [ADVAPI32.@]
366  * SystemFunction017  [ADVAPI32.@]
367  * SystemFunction019  [ADVAPI32.@]
368  * SystemFunction021  [ADVAPI32.@]
369  * SystemFunction023  [ADVAPI32.@]
370  *
371  * Decrypts two DES blocks with two keys
372  *
373  * PARAMS
374  *   data    [I] data to decrypt (16 bytes)
375  *   key     [I] key data (two lots of 7 bytes)
376  *   output  [O] buffer to receive decrypted data (16 bytes)
377  *
378  * RETURNS
379  *  Success: STATUS_SUCCESS
380  *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
381  */
382 NTSTATUS
SystemFunction013(const BYTE * in,const BYTE * key,LPBYTE out)383 WINAPI SystemFunction013(const BYTE *in, const BYTE *key, LPBYTE out)
384 {
385     if (!in || !out)
386         return STATUS_UNSUCCESSFUL;
387     CRYPT_DESunhash(out, key, in);
388     CRYPT_DESunhash(out+8, key+7, in+8);
389     return STATUS_SUCCESS;
390 }
391 
392 /******************************************************************************
393  * SystemFunction024  [ADVAPI32.@]
394  *
395  * Encrypts two DES blocks with a 32 bit key...
396  *
397  * PARAMS
398  *   data    [I] data to encrypt (16 bytes)
399  *   key     [I] key data (4 bytes)
400  *   output  [O] buffer to receive encrypted data (16 bytes)
401  *
402  * RETURNS
403  *  Success: STATUS_SUCCESS
404  */
405 NTSTATUS
SystemFunction024(const BYTE * in,const BYTE * key,LPBYTE out)406 WINAPI SystemFunction024(const BYTE *in, const BYTE *key, LPBYTE out)
407 {
408     BYTE deskey[0x10];
409 
410     memcpy(deskey, key, 4);
411     memcpy(deskey+4, key, 4);
412     memcpy(deskey+8, key, 4);
413     memcpy(deskey+12, key, 4);
414 
415     CRYPT_DEShash(out, deskey, in);
416     CRYPT_DEShash(out+8, deskey+7, in+8);
417 
418     return STATUS_SUCCESS;
419 }
420 
421 /******************************************************************************
422  * SystemFunction025  [ADVAPI32.@]
423  *
424  * Decrypts two DES blocks with a 32 bit key...
425  *
426  * PARAMS
427  *   data    [I] data to encrypt (16 bytes)
428  *   key     [I] key data (4 bytes)
429  *   output  [O] buffer to receive encrypted data (16 bytes)
430  *
431  * RETURNS
432  *  Success: STATUS_SUCCESS
433  */
434 NTSTATUS
SystemFunction025(const BYTE * in,const BYTE * key,LPBYTE out)435 WINAPI SystemFunction025(const BYTE *in, const BYTE *key, LPBYTE out)
436 {
437     BYTE deskey[0x10];
438 
439     memcpy(deskey, key, 4);
440     memcpy(deskey+4, key, 4);
441     memcpy(deskey+8, key, 4);
442     memcpy(deskey+12, key, 4);
443 
444     CRYPT_DESunhash(out, deskey, in);
445     CRYPT_DESunhash(out+8, deskey+7, in+8);
446 
447     return STATUS_SUCCESS;
448 }
449 
450 /**********************************************************************
451  * SystemFunction028  [ADVAPI32.@]
452  *
453  * Retrieves an encryption session key...
454  *
455  * PARAMS
456  *   ContextHandle [I] RPC context handle
457  *   SessionKey    [O] buffer to receive the session key (16 bytes)
458  *
459  * RETURNS
460  *  Success: STATUS_LOCAL_USER_SESSION_KEY
461  *
462  * @unimplemented
463  */
464 NTSTATUS
465 WINAPI
SystemFunction028(_In_ PVOID ContextHandle,_Out_ LPBYTE SessionKey)466 SystemFunction028(
467     _In_ PVOID ContextHandle,
468     _Out_ LPBYTE SessionKey)
469 {
470     /* HACK: Always return the default key */
471     memcpy(SessionKey, DefaultSessionKey, sizeof(DefaultSessionKey));
472     return STATUS_LOCAL_USER_SESSION_KEY;
473 
474 #if 0
475     //NDRCContextBinding();
476     //SystemFunction034()
477     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
478     return 28;
479 #endif
480 }
481 
482 
483 /**********************************************************************
484  *
485  * @unimplemented
486  */
487 INT
488 WINAPI
SystemFunction029(INT a,INT b)489 SystemFunction029(INT a, INT b)
490 {
491     //I_RpcBindingIsClientLocal()
492     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
493     return 29;
494 }
495 
496 
497 /******************************************************************************
498  * SystemFunction030   (ADVAPI32.@)
499  *
500  * Tests if two blocks of 16 bytes are equal
501  *
502  * PARAMS
503  *  b1,b2   [I] block of 16 bytes
504  *
505  * RETURNS
506  *  TRUE  if blocks are the same
507  *  FALSE if blocks are different
508  */
509 BOOL
SystemFunction030(LPCVOID b1,LPCVOID b2)510 WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
511 {
512     return !memcmp(b1, b2, 0x10);
513 }
514 
515 
516 /******************************************************************************
517  * SystemFunction032  [ADVAPI32.@]
518  *
519  * Encrypts a string data using ARC4
520  *
521  * PARAMS
522  *   data    [I/O] data to encrypt
523  *   key     [I] key data
524  *
525  * RETURNS
526  *  Success: STATUS_SUCCESS
527  *  Failure: STATUS_UNSUCCESSFUL
528  *
529  * NOTES
530  *  see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
531  */
532 NTSTATUS
SystemFunction032(struct ustring * data,const struct ustring * key)533 WINAPI SystemFunction032(struct ustring *data, const struct ustring *key)
534 {
535     RC4_CONTEXT a4i;
536 
537     rc4_init(&a4i, key->Buffer, key->Length);
538     rc4_crypt(&a4i, data->Buffer, data->Length);
539 
540     return STATUS_SUCCESS;
541 }
542 
543 
544 /**********************************************************************
545  *
546  * @unimplemented
547  */
548 INT
549 WINAPI
SystemFunction033(INT a,INT b)550 SystemFunction033(INT a, INT b)
551 {
552     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
553     return 33;
554 }
555 
556 /**********************************************************************
557  *
558  * @unimplemented
559  */
560 INT
561 WINAPI
SystemFunction034(INT a,INT b)562 SystemFunction034(INT a, INT b)
563 {
564     //RpcBindingToStringBindingW
565     //I_RpcMapWin32Status
566     //RpcStringBindingParseW
567     //RpcStringFreeW
568     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
569     return 34;
570 }
571 
572 
573 /******************************************************************************
574  * SystemFunction035   (ADVAPI32.@)
575  *
576  * Described here:
577 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
578  *
579  * NOTES
580  *  Stub, always return TRUE.
581  */
SystemFunction035(LPCSTR lpszDllFilePath)582 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
583 {
584     //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
585     return TRUE;
586 }
587 
588 /******************************************************************************
589  * SystemFunction036   (ADVAPI32.@)
590  *
591  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
592  *
593  * PARAMS
594  *  pbBuffer [O] Pointer to memory to receive random bytes.
595  *  dwLen    [I] Number of random bytes to fetch.
596  *
597  * RETURNS
598  *  Always TRUE in my tests
599  */
600 BOOLEAN
601 WINAPI
SystemFunction036(PVOID pbBuffer,ULONG dwLen)602 SystemFunction036(PVOID pbBuffer, ULONG dwLen)
603 {
604     ////////////////////////////////////////////////////////////////
605     //////////////////// B I G   W A R N I N G  !!! ////////////////
606     // This function will output numbers based on the tick count. //
607     // It will NOT OUTPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!!    //
608     ////////////////////////////////////////////////////////////////
609 
610     DWORD dwSeed;
611     PBYTE pBuffer;
612     ULONG uPseudoRandom;
613     LARGE_INTEGER time;
614     static ULONG uCounter = 17;
615 
616     if(!pbBuffer || !dwLen)
617     {
618         /* This function always returns TRUE, even if invalid parameters were passed. (verified under WinXP SP2) */
619         return TRUE;
620     }
621 
622     /* Get the first seed from the performance counter */
623     QueryPerformanceCounter(&time);
624     dwSeed = time.LowPart ^ time.HighPart ^ RtlUlongByteSwap(uCounter++);
625 
626     /* We will access the buffer bytewise */
627     pBuffer = (PBYTE)pbBuffer;
628 
629     do
630     {
631         /* Use the pseudo random number generator RtlRandom, which outputs a 4-byte value and a new seed */
632         uPseudoRandom = RtlRandom(&dwSeed);
633 
634         do
635         {
636             /* Get each byte from the pseudo random number and store it in the buffer */
637             *pBuffer = (BYTE)(uPseudoRandom >> 8 * (dwLen % 3) & 0xFF);
638             ++pBuffer;
639         } while(--dwLen % 3);
640     } while(dwLen);
641 
642     return TRUE;
643 }
644 
645 HANDLE KsecDeviceHandle;
646 
647 static
648 NTSTATUS
KsecOpenDevice()649 KsecOpenDevice()
650 {
651     UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KsecDD");
652     OBJECT_ATTRIBUTES ObjectAttributes;
653     IO_STATUS_BLOCK IoStatusBlock;
654     HANDLE DeviceHandle;
655     NTSTATUS Status;
656 
657     InitializeObjectAttributes(&ObjectAttributes,
658                                &DeviceName,
659                                OBJ_CASE_INSENSITIVE,
660                                NULL,
661                                NULL);
662     Status = NtOpenFile(&DeviceHandle,
663                         FILE_READ_DATA | SYNCHRONIZE,
664                         &ObjectAttributes,
665                         &IoStatusBlock,
666                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
667                         FILE_SYNCHRONOUS_IO_NONALERT);
668     if (!NT_SUCCESS(Status))
669     {
670         return Status;
671     }
672 
673     if (InterlockedCompareExchangePointer(&KsecDeviceHandle, DeviceHandle, NULL) != NULL)
674     {
675         NtClose(DeviceHandle);
676     }
677 
678     return STATUS_SUCCESS;
679 }
680 
681 VOID
CloseKsecDdHandle(VOID)682 CloseKsecDdHandle(VOID)
683 {
684     /* Check if we already opened a handle to ksecdd */
685     if (KsecDeviceHandle != NULL)
686     {
687         /* Close it */
688         CloseHandle(KsecDeviceHandle);
689         KsecDeviceHandle = NULL;
690     }
691 }
692 
693 static
694 NTSTATUS
KsecDeviceIoControl(ULONG IoControlCode,PVOID InputBuffer,SIZE_T InputBufferLength,PVOID OutputBuffer,SIZE_T OutputBufferLength)695 KsecDeviceIoControl(
696     ULONG IoControlCode,
697     PVOID InputBuffer,
698     SIZE_T InputBufferLength,
699     PVOID OutputBuffer,
700     SIZE_T OutputBufferLength)
701 {
702     IO_STATUS_BLOCK IoStatusBlock;
703     NTSTATUS Status;
704 
705     /* Check if we already have a handle */
706     if (KsecDeviceHandle == NULL)
707     {
708         /* Try to open the device */
709         Status = KsecOpenDevice();
710         if (!NT_SUCCESS(Status))
711         {
712             //ERR("Failed to open handle to KsecDd driver!\n");
713             return Status;
714         }
715     }
716 
717     /* Call the driver */
718     Status = NtDeviceIoControlFile(KsecDeviceHandle,
719                                    NULL,
720                                    NULL,
721                                    NULL,
722                                    &IoStatusBlock,
723                                    IoControlCode,
724                                    InputBuffer,
725                                    InputBufferLength,
726                                    OutputBuffer,
727                                    OutputBufferLength);
728 
729     return Status;
730 }
731 
732 /*
733    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
734    in crypt32.dll.
735  */
736 
737 /******************************************************************************
738  * SystemFunction040   (ADVAPI32.@)
739  *
740  * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
741  *
742  * PARAMS
743  *  memory [I/O] Pointer to memory to encrypt.
744  *  length [I] Length of region to encrypt in bytes.
745  *  flags  [I] Control whether other processes are able to decrypt the memory.
746  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
747  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
748  *    RTL_ENCRYPT_OPTION_SAME_LOGON
749  *
750  * RETURNS
751  *  Success: STATUS_SUCCESS
752  *  Failure: NTSTATUS error code
753  *
754  * NOTES
755  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
756  *  If flags are specified when encrypting, the same flag value must be given
757  *  when decrypting the memory.
758  */
759 NTSTATUS
760 WINAPI
SystemFunction040(_Inout_ PVOID Memory,_In_ ULONG MemoryLength,_In_ ULONG OptionFlags)761 SystemFunction040(
762     _Inout_ PVOID Memory,
763     _In_ ULONG MemoryLength,
764     _In_ ULONG OptionFlags)
765 {
766     ULONG IoControlCode;
767 
768     if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
769     {
770         IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_PROCESS;
771     }
772     else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
773     {
774         IoControlCode = IOCTL_KSEC_ENCRYPT_CROSS_PROCESS;
775     }
776     else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
777     {
778         IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_LOGON;
779     }
780     else
781     {
782         return STATUS_INVALID_PARAMETER;
783     }
784 
785     return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
786 }
787 
788 /******************************************************************************
789  * SystemFunction041  (ADVAPI32.@)
790  *
791  * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
792  *
793  * PARAMS
794  *  memory [I/O] Pointer to memory to decrypt.
795  *  length [I] Length of region to decrypt in bytes.
796  *  flags  [I] Control whether other processes are able to decrypt the memory.
797  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
798  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
799  *    RTL_ENCRYPT_OPTION_SAME_LOGON
800  *
801  * RETURNS
802  *  Success: STATUS_SUCCESS
803  *  Failure: NTSTATUS error code
804  *
805  * NOTES
806  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
807  *  If flags are specified when encrypting, the same flag value must be given
808  *  when decrypting the memory.
809  */
810 NTSTATUS
811 WINAPI
SystemFunction041(_Inout_ PVOID Memory,_In_ ULONG MemoryLength,_In_ ULONG OptionFlags)812 SystemFunction041(
813     _Inout_ PVOID Memory,
814     _In_ ULONG MemoryLength,
815     _In_ ULONG OptionFlags)
816 {
817     ULONG IoControlCode;
818 
819     if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
820     {
821         IoControlCode = IOCTL_KSEC_DECRYPT_SAME_PROCESS;
822     }
823     else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
824     {
825         IoControlCode = IOCTL_KSEC_DECRYPT_CROSS_PROCESS;
826     }
827     else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
828     {
829         IoControlCode = IOCTL_KSEC_DECRYPT_SAME_LOGON;
830     }
831     else
832     {
833         return STATUS_INVALID_PARAMETER;
834     }
835 
836     return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
837 }
838 
839 /* EOF */
840