2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/advapi32/misc/sysfun.c
5 * PURPOSE: advapi32.dll system functions (undocumented)
6 * PROGRAMMER: Emanuele Aliberti
10 * 20080424 Ported from WINE
15 #include <ksecioctl.h>
20 static const unsigned char CRYPT_LMhash_Magic
[8] =
21 { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
23 /******************************************************************************
24 * SystemFunction001 [ADVAPI32.@]
26 * Encrypts a single block of data using DES
29 * data [I] data to encrypt (8 bytes)
30 * key [I] key data (7 bytes)
31 * output [O] the encrypted data (8 bytes)
34 * Success: STATUS_SUCCESS
35 * Failure: STATUS_UNSUCCESSFUL
39 WINAPI
SystemFunction001(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
42 return STATUS_UNSUCCESSFUL
;
43 CRYPT_DEShash(output
, key
, data
);
44 return STATUS_SUCCESS
;
48 /******************************************************************************
49 * SystemFunction002 [ADVAPI32.@]
51 * Decrypts a single block of data using DES
54 * data [I] data to decrypt (8 bytes)
55 * key [I] key data (7 bytes)
56 * output [O] the decrypted data (8 bytes)
59 * Success: STATUS_SUCCESS
60 * Failure: STATUS_UNSUCCESSFUL
64 WINAPI
SystemFunction002(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
67 return STATUS_UNSUCCESSFUL
;
68 CRYPT_DESunhash(output
, key
, data
);
69 return STATUS_SUCCESS
;
73 /******************************************************************************
74 * SystemFunction003 [ADVAPI32.@]
76 * Hashes a key using DES and a fixed datablock
79 * key [I] key data (7 bytes)
80 * output [O] hashed key (8 bytes)
83 * Success: STATUS_SUCCESS
84 * Failure: STATUS_UNSUCCESSFUL
88 WINAPI
SystemFunction003(const BYTE
*key
, LPBYTE output
)
91 return STATUS_UNSUCCESSFUL
;
92 CRYPT_DEShash(output
, key
, CRYPT_LMhash_Magic
);
93 return STATUS_SUCCESS
;
97 /******************************************************************************
98 * SystemFunction004 [ADVAPI32.@]
100 * Encrypts a block of data with DES in ECB mode, preserving the length
103 * data [I] data to encrypt
104 * key [I] key data (up to 7 bytes)
105 * output [O] buffer to receive encrypted data
108 * Success: STATUS_SUCCESS
109 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
110 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
113 * Encrypt buffer size should be input size rounded up to 8 bytes
114 * plus an extra 8 bytes.
117 WINAPI
SystemFunction004(const struct ustring
*in
,
118 const struct ustring
*key
,
125 unsigned char deskey
[7];
126 unsigned int crypt_len
, ofs
;
129 return STATUS_INVALID_PARAMETER_2
;
131 crypt_len
= ((in
->Length
+7)&~7);
132 if (out
->MaximumLength
< (crypt_len
+8))
133 return STATUS_BUFFER_TOO_SMALL
;
135 data
.ui
[0] = in
->Length
;
138 if (key
->Length
<sizeof deskey
)
140 memset(deskey
, 0, sizeof deskey
);
141 memcpy(deskey
, key
->Buffer
, key
->Length
);
144 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
146 CRYPT_DEShash(out
->Buffer
, deskey
, data
.uc
);
148 for(ofs
=0; ofs
<(crypt_len
-8); ofs
+=8)
149 CRYPT_DEShash(out
->Buffer
+8+ofs
, deskey
, in
->Buffer
+ofs
);
151 memset(data
.uc
, 0, sizeof data
.uc
);
152 memcpy(data
.uc
, in
->Buffer
+ofs
, in
->Length
+8-crypt_len
);
153 CRYPT_DEShash(out
->Buffer
+8+ofs
, deskey
, data
.uc
);
155 out
->Length
= crypt_len
+8;
157 return STATUS_SUCCESS
;
160 /******************************************************************************
161 * SystemFunction005 [ADVAPI32.@]
163 * Decrypts a block of data with DES in ECB mode
166 * data [I] data to decrypt
167 * key [I] key data (up to 7 bytes)
168 * output [O] buffer to receive decrypted data
171 * Success: STATUS_SUCCESS
172 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
173 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
177 WINAPI
SystemFunction005(const struct ustring
*in
,
178 const struct ustring
*key
,
185 unsigned char deskey
[7];
186 unsigned int ofs
, crypt_len
;
189 return STATUS_INVALID_PARAMETER_2
;
191 if (key
->Length
<sizeof deskey
)
193 memset(deskey
, 0, sizeof deskey
);
194 memcpy(deskey
, key
->Buffer
, key
->Length
);
197 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
199 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
);
202 return STATUS_UNKNOWN_REVISION
;
204 crypt_len
= data
.ui
[0];
205 if (crypt_len
> out
->MaximumLength
)
206 return STATUS_BUFFER_TOO_SMALL
;
208 for (ofs
=0; (ofs
+8)<crypt_len
; ofs
+=8)
209 CRYPT_DESunhash(out
->Buffer
+ofs
, deskey
, in
->Buffer
+ofs
+8);
213 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
+ofs
+8);
214 memcpy(out
->Buffer
+ofs
, data
.uc
, crypt_len
-ofs
);
217 out
->Length
= crypt_len
;
219 return STATUS_SUCCESS
;
222 /******************************************************************************
223 * SystemFunction007 [ADVAPI32.@]
225 * MD4 hash a unicode string
228 * string [I] the string to hash
229 * output [O] the md4 hash of the string (16 bytes)
232 * Success: STATUS_SUCCESS
233 * Failure: STATUS_UNSUCCESSFUL
237 WINAPI
SystemFunction007(const UNICODE_STRING
*string
, LPBYTE hash
)
242 MD4Update( &ctx
, (const BYTE
*)string
->Buffer
, string
->Length
);
244 memcpy( hash
, ctx
.digest
, 0x10 );
246 return STATUS_SUCCESS
;
249 /******************************************************************************
250 * SystemFunction008 [ADVAPI32.@]
252 * Creates a LM response from a challenge and a password hash
255 * challenge [I] Challenge from authentication server
256 * hash [I] NTLM hash (from SystemFunction006)
257 * response [O] response to send back to the server
260 * Success: STATUS_SUCCESS
261 * Failure: STATUS_UNSUCCESSFUL
264 * see http://davenport.sourceforge.net/ntlm.html#theLmResponse
268 WINAPI
SystemFunction008(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
272 if (!challenge
|| !response
)
273 return STATUS_UNSUCCESSFUL
;
275 memset(key
, 0, sizeof key
);
276 memcpy(key
, hash
, 0x10);
278 CRYPT_DEShash(response
, key
, challenge
);
279 CRYPT_DEShash(response
+8, key
+7, challenge
);
280 CRYPT_DEShash(response
+16, key
+14, challenge
);
282 return STATUS_SUCCESS
;
285 /******************************************************************************
286 * SystemFunction009 [ADVAPI32.@]
288 * Seems to do the same as SystemFunction008...
291 WINAPI
SystemFunction009(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
293 return SystemFunction008(challenge
, hash
, response
);
296 /******************************************************************************
297 * SystemFunction010 [ADVAPI32.@]
298 * SystemFunction011 [ADVAPI32.@]
300 * MD4 hashes 16 bytes of data
303 * unknown [] seems to have no effect on the output
304 * data [I] pointer to data to hash (16 bytes)
305 * output [O] the md4 hash of the data (16 bytes)
308 * Success: STATUS_SUCCESS
309 * Failure: STATUS_UNSUCCESSFUL
313 WINAPI
SystemFunction010(LPVOID unknown
, const BYTE
*data
, LPBYTE hash
)
318 MD4Update( &ctx
, data
, 0x10 );
320 memcpy( hash
, ctx
.digest
, 0x10 );
322 return STATUS_SUCCESS
;
325 /******************************************************************************
326 * SystemFunction012 [ADVAPI32.@]
327 * SystemFunction014 [ADVAPI32.@]
328 * SystemFunction016 [ADVAPI32.@]
329 * SystemFunction018 [ADVAPI32.@]
330 * SystemFunction020 [ADVAPI32.@]
331 * SystemFunction022 [ADVAPI32.@]
333 * Encrypts two DES blocks with two keys
336 * data [I] data to encrypt (16 bytes)
337 * key [I] key data (two lots of 7 bytes)
338 * output [O] buffer to receive encrypted data (16 bytes)
341 * Success: STATUS_SUCCESS
342 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
345 WINAPI
SystemFunction012(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
348 return STATUS_UNSUCCESSFUL
;
350 CRYPT_DEShash(out
, key
, in
);
351 CRYPT_DEShash(out
+8, key
+7, in
+8);
352 return STATUS_SUCCESS
;
355 /******************************************************************************
356 * SystemFunction013 [ADVAPI32.@]
357 * SystemFunction015 [ADVAPI32.@]
358 * SystemFunction017 [ADVAPI32.@]
359 * SystemFunction019 [ADVAPI32.@]
360 * SystemFunction021 [ADVAPI32.@]
361 * SystemFunction023 [ADVAPI32.@]
363 * Decrypts two DES blocks with two keys
366 * data [I] data to decrypt (16 bytes)
367 * key [I] key data (two lots of 7 bytes)
368 * output [O] buffer to receive decrypted data (16 bytes)
371 * Success: STATUS_SUCCESS
372 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
375 WINAPI
SystemFunction013(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
378 return STATUS_UNSUCCESSFUL
;
379 CRYPT_DESunhash(out
, key
, in
);
380 CRYPT_DESunhash(out
+8, key
+7, in
+8);
381 return STATUS_SUCCESS
;
384 /******************************************************************************
385 * SystemFunction024 [ADVAPI32.@]
387 * Encrypts two DES blocks with a 32 bit key...
390 * data [I] data to encrypt (16 bytes)
391 * key [I] key data (4 bytes)
392 * output [O] buffer to receive encrypted data (16 bytes)
395 * Success: STATUS_SUCCESS
398 WINAPI
SystemFunction024(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
402 memcpy(deskey
, key
, 4);
403 memcpy(deskey
+4, key
, 4);
404 memcpy(deskey
+8, key
, 4);
405 memcpy(deskey
+12, key
, 4);
407 CRYPT_DEShash(out
, deskey
, in
);
408 CRYPT_DEShash(out
+8, deskey
+7, in
+8);
410 return STATUS_SUCCESS
;
413 /******************************************************************************
414 * SystemFunction025 [ADVAPI32.@]
416 * Decrypts two DES blocks with a 32 bit key...
419 * data [I] data to encrypt (16 bytes)
420 * key [I] key data (4 bytes)
421 * output [O] buffer to receive encrypted data (16 bytes)
424 * Success: STATUS_SUCCESS
427 WINAPI
SystemFunction025(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
431 memcpy(deskey
, key
, 4);
432 memcpy(deskey
+4, key
, 4);
433 memcpy(deskey
+8, key
, 4);
434 memcpy(deskey
+12, key
, 4);
436 CRYPT_DESunhash(out
, deskey
, in
);
437 CRYPT_DESunhash(out
+8, deskey
+7, in
+8);
439 return STATUS_SUCCESS
;
442 /**********************************************************************
448 SystemFunction028(INT a
, INT b
)
450 //NDRCContextBinding()
451 //SystemFunction034()
452 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
457 /**********************************************************************
463 SystemFunction029(INT a
, INT b
)
465 //I_RpcBindingIsClientLocal()
466 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
471 /******************************************************************************
472 * SystemFunction030 (ADVAPI32.@)
474 * Tests if two blocks of 16 bytes are equal
477 * b1,b2 [I] block of 16 bytes
480 * TRUE if blocks are the same
481 * FALSE if blocks are different
484 WINAPI
SystemFunction030(LPCVOID b1
, LPCVOID b2
)
486 return !memcmp(b1
, b2
, 0x10);
490 /******************************************************************************
491 * SystemFunction032 [ADVAPI32.@]
493 * Encrypts a string data using ARC4
496 * data [I/O] data to encrypt
500 * Success: STATUS_SUCCESS
501 * Failure: STATUS_UNSUCCESSFUL
504 * see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
507 WINAPI
SystemFunction032(struct ustring
*data
, const struct ustring
*key
)
511 rc4_init(&a4i
, key
->Buffer
, key
->Length
);
512 rc4_crypt(&a4i
, data
->Buffer
, data
->Length
);
514 return STATUS_SUCCESS
;
518 /**********************************************************************
524 SystemFunction033(INT a
, INT b
)
526 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
530 /**********************************************************************
536 SystemFunction034(INT a
, INT b
)
538 //RpcBindingToStringBindingW
539 //I_RpcMapWin32Status
540 //RpcStringBindingParseW
542 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
547 /******************************************************************************
548 * SystemFunction035 (ADVAPI32.@)
551 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
554 * Stub, always return TRUE.
556 BOOL WINAPI
SystemFunction035(LPCSTR lpszDllFilePath
)
558 //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
562 /******************************************************************************
563 * SystemFunction036 (ADVAPI32.@)
565 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
568 * pbBuffer [O] Pointer to memory to receive random bytes.
569 * dwLen [I] Number of random bytes to fetch.
572 * Always TRUE in my tests
576 SystemFunction036(PVOID pbBuffer
, ULONG dwLen
)
578 ////////////////////////////////////////////////////////////////
579 //////////////////// B I G W A R N I N G !!! ////////////////
580 // This function will output numbers based on the tick count. //
581 // It will NOT OUTPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!! //
582 ////////////////////////////////////////////////////////////////
588 static ULONG uCounter
= 17;
590 if(!pbBuffer
|| !dwLen
)
592 /* This function always returns TRUE, even if invalid parameters were passed. (verified under WinXP SP2) */
596 /* Get the first seed from the performance counter */
597 QueryPerformanceCounter(&time
);
598 dwSeed
= time
.LowPart
^ time
.HighPart
^ RtlUlongByteSwap(uCounter
++);
600 /* We will access the buffer bytewise */
601 pBuffer
= (PBYTE
)pbBuffer
;
605 /* Use the pseudo random number generator RtlRandom, which outputs a 4-byte value and a new seed */
606 uPseudoRandom
= RtlRandom(&dwSeed
);
610 /* Get each byte from the pseudo random number and store it in the buffer */
611 *pBuffer
= (BYTE
)(uPseudoRandom
>> 8 * (dwLen
% 3) & 0xFF);
613 } while(--dwLen
% 3);
619 HANDLE KsecDeviceHandle
;
625 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\KsecDD");
626 OBJECT_ATTRIBUTES ObjectAttributes
;
627 IO_STATUS_BLOCK IoStatusBlock
;
631 InitializeObjectAttributes(&ObjectAttributes
,
633 OBJ_CASE_INSENSITIVE
,
636 Status
= NtOpenFile(&DeviceHandle
,
637 FILE_READ_DATA
| SYNCHRONIZE
,
640 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
641 FILE_SYNCHRONOUS_IO_NONALERT
);
642 if (!NT_SUCCESS(Status
))
647 if (InterlockedCompareExchangePointer(&KsecDeviceHandle
, DeviceHandle
, NULL
) != NULL
)
649 NtClose(DeviceHandle
);
652 return STATUS_SUCCESS
;
656 CloseKsecDdHandle(VOID
)
658 /* Check if we already opened a handle to ksecdd */
659 if (KsecDeviceHandle
!= NULL
)
662 CloseHandle(KsecDeviceHandle
);
663 KsecDeviceHandle
= NULL
;
672 SIZE_T InputBufferLength
,
674 SIZE_T OutputBufferLength
)
676 IO_STATUS_BLOCK IoStatusBlock
;
679 /* Check if we already have a handle */
680 if (KsecDeviceHandle
== NULL
)
682 /* Try to open the device */
683 Status
= KsecOpenDevice();
684 if (!NT_SUCCESS(Status
))
686 //ERR("Failed to open handle to KsecDd driver!\n");
691 /* Call the driver */
692 Status
= NtDeviceIoControlFile(KsecDeviceHandle
,
707 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
711 /******************************************************************************
712 * SystemFunction040 (ADVAPI32.@)
714 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
717 * memory [I/O] Pointer to memory to encrypt.
718 * length [I] Length of region to encrypt in bytes.
719 * flags [I] Control whether other processes are able to decrypt the memory.
720 * RTL_ENCRYPT_OPTION_SAME_PROCESS
721 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
722 * RTL_ENCRYPT_OPTION_SAME_LOGON
725 * Success: STATUS_SUCCESS
726 * Failure: NTSTATUS error code
729 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
730 * If flags are specified when encrypting, the same flag value must be given
731 * when decrypting the memory.
736 _Inout_ PVOID Memory
,
737 _In_ ULONG MemoryLength
,
738 _In_ ULONG OptionFlags
)
742 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
744 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_PROCESS
;
746 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
748 IoControlCode
= IOCTL_KSEC_ENCRYPT_CROSS_PROCESS
;
750 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
752 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_LOGON
;
756 return STATUS_INVALID_PARAMETER
;
759 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);
762 /******************************************************************************
763 * SystemFunction041 (ADVAPI32.@)
765 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
768 * memory [I/O] Pointer to memory to decrypt.
769 * length [I] Length of region to decrypt in bytes.
770 * flags [I] Control whether other processes are able to decrypt the memory.
771 * RTL_ENCRYPT_OPTION_SAME_PROCESS
772 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
773 * RTL_ENCRYPT_OPTION_SAME_LOGON
776 * Success: STATUS_SUCCESS
777 * Failure: NTSTATUS error code
780 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
781 * If flags are specified when encrypting, the same flag value must be given
782 * when decrypting the memory.
787 _Inout_ PVOID Memory
,
788 _In_ ULONG MemoryLength
,
789 _In_ ULONG OptionFlags
)
793 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
795 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_PROCESS
;
797 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
799 IoControlCode
= IOCTL_KSEC_DECRYPT_CROSS_PROCESS
;
801 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
803 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_LOGON
;
807 return STATUS_INVALID_PARAMETER
;
810 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);