3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: dll/win32/advapi32/misc/sysfun.c
6 * PURPOSE: advapi32.dll system functions (undocumented)
7 * PROGRAMMER: Emanuele Aliberti
11 * 20080424 Ported from WINE
16 #include <ksecioctl.h>
21 static const unsigned char CRYPT_LMhash_Magic
[8] =
22 { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
24 /******************************************************************************
25 * SystemFunction001 [ADVAPI32.@]
27 * Encrypts a single block of data using DES
30 * data [I] data to encrypt (8 bytes)
31 * key [I] key data (7 bytes)
32 * output [O] the encrypted data (8 bytes)
35 * Success: STATUS_SUCCESS
36 * Failure: STATUS_UNSUCCESSFUL
40 WINAPI
SystemFunction001(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
43 return STATUS_UNSUCCESSFUL
;
44 CRYPT_DEShash(output
, key
, data
);
45 return STATUS_SUCCESS
;
49 /******************************************************************************
50 * SystemFunction002 [ADVAPI32.@]
52 * Decrypts a single block of data using DES
55 * data [I] data to decrypt (8 bytes)
56 * key [I] key data (7 bytes)
57 * output [O] the decrypted data (8 bytes)
60 * Success: STATUS_SUCCESS
61 * Failure: STATUS_UNSUCCESSFUL
65 WINAPI
SystemFunction002(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
68 return STATUS_UNSUCCESSFUL
;
69 CRYPT_DESunhash(output
, key
, data
);
70 return STATUS_SUCCESS
;
74 /******************************************************************************
75 * SystemFunction003 [ADVAPI32.@]
77 * Hashes a key using DES and a fixed datablock
80 * key [I] key data (7 bytes)
81 * output [O] hashed key (8 bytes)
84 * Success: STATUS_SUCCESS
85 * Failure: STATUS_UNSUCCESSFUL
89 WINAPI
SystemFunction003(const BYTE
*key
, LPBYTE output
)
92 return STATUS_UNSUCCESSFUL
;
93 CRYPT_DEShash(output
, key
, CRYPT_LMhash_Magic
);
94 return STATUS_SUCCESS
;
98 /******************************************************************************
99 * SystemFunction004 [ADVAPI32.@]
101 * Encrypts a block of data with DES in ECB mode, preserving the length
104 * data [I] data to encrypt
105 * key [I] key data (up to 7 bytes)
106 * output [O] buffer to receive encrypted data
109 * Success: STATUS_SUCCESS
110 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
111 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
114 * Encrypt buffer size should be input size rounded up to 8 bytes
115 * plus an extra 8 bytes.
118 WINAPI
SystemFunction004(const struct ustring
*in
,
119 const struct ustring
*key
,
126 unsigned char deskey
[7];
127 unsigned int crypt_len
, ofs
;
130 return STATUS_INVALID_PARAMETER_2
;
132 crypt_len
= ((in
->Length
+7)&~7);
133 if (out
->MaximumLength
< (crypt_len
+8))
134 return STATUS_BUFFER_TOO_SMALL
;
136 data
.ui
[0] = in
->Length
;
139 if (key
->Length
<sizeof deskey
)
141 memset(deskey
, 0, sizeof deskey
);
142 memcpy(deskey
, key
->Buffer
, key
->Length
);
145 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
147 CRYPT_DEShash(out
->Buffer
, deskey
, data
.uc
);
149 for(ofs
=0; ofs
<(crypt_len
-8); ofs
+=8)
150 CRYPT_DEShash(out
->Buffer
+8+ofs
, deskey
, in
->Buffer
+ofs
);
152 memset(data
.uc
, 0, sizeof data
.uc
);
153 memcpy(data
.uc
, in
->Buffer
+ofs
, in
->Length
+8-crypt_len
);
154 CRYPT_DEShash(out
->Buffer
+8+ofs
, deskey
, data
.uc
);
156 out
->Length
= crypt_len
+8;
158 return STATUS_SUCCESS
;
161 /******************************************************************************
162 * SystemFunction005 [ADVAPI32.@]
164 * Decrypts a block of data with DES in ECB mode
167 * data [I] data to decrypt
168 * key [I] key data (up to 7 bytes)
169 * output [O] buffer to receive decrypted data
172 * Success: STATUS_SUCCESS
173 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
174 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
178 WINAPI
SystemFunction005(const struct ustring
*in
,
179 const struct ustring
*key
,
186 unsigned char deskey
[7];
187 unsigned int ofs
, crypt_len
;
190 return STATUS_INVALID_PARAMETER_2
;
192 if (key
->Length
<sizeof deskey
)
194 memset(deskey
, 0, sizeof deskey
);
195 memcpy(deskey
, key
->Buffer
, key
->Length
);
198 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
200 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
);
203 return STATUS_UNKNOWN_REVISION
;
205 crypt_len
= data
.ui
[0];
206 if (crypt_len
> out
->MaximumLength
)
207 return STATUS_BUFFER_TOO_SMALL
;
209 for (ofs
=0; (ofs
+8)<crypt_len
; ofs
+=8)
210 CRYPT_DESunhash(out
->Buffer
+ofs
, deskey
, in
->Buffer
+ofs
+8);
214 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
+ofs
+8);
215 memcpy(out
->Buffer
+ofs
, data
.uc
, crypt_len
-ofs
);
218 out
->Length
= crypt_len
;
220 return STATUS_SUCCESS
;
223 /******************************************************************************
224 * SystemFunction007 [ADVAPI32.@]
226 * MD4 hash a unicode string
229 * string [I] the string to hash
230 * output [O] the md4 hash of the string (16 bytes)
233 * Success: STATUS_SUCCESS
234 * Failure: STATUS_UNSUCCESSFUL
238 WINAPI
SystemFunction007(const UNICODE_STRING
*string
, LPBYTE hash
)
243 MD4Update( &ctx
, (const BYTE
*)string
->Buffer
, string
->Length
);
245 memcpy( hash
, ctx
.digest
, 0x10 );
247 return STATUS_SUCCESS
;
250 /******************************************************************************
251 * SystemFunction008 [ADVAPI32.@]
253 * Creates a LM response from a challenge and a password hash
256 * challenge [I] Challenge from authentication server
257 * hash [I] NTLM hash (from SystemFunction006)
258 * response [O] response to send back to the server
261 * Success: STATUS_SUCCESS
262 * Failure: STATUS_UNSUCCESSFUL
265 * see http://davenport.sourceforge.net/ntlm.html#theLmResponse
269 WINAPI
SystemFunction008(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
273 if (!challenge
|| !response
)
274 return STATUS_UNSUCCESSFUL
;
276 memset(key
, 0, sizeof key
);
277 memcpy(key
, hash
, 0x10);
279 CRYPT_DEShash(response
, key
, challenge
);
280 CRYPT_DEShash(response
+8, key
+7, challenge
);
281 CRYPT_DEShash(response
+16, key
+14, challenge
);
283 return STATUS_SUCCESS
;
286 /******************************************************************************
287 * SystemFunction009 [ADVAPI32.@]
289 * Seems to do the same as SystemFunction008...
292 WINAPI
SystemFunction009(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
294 return SystemFunction008(challenge
, hash
, response
);
297 /******************************************************************************
298 * SystemFunction010 [ADVAPI32.@]
299 * SystemFunction011 [ADVAPI32.@]
301 * MD4 hashes 16 bytes of data
304 * unknown [] seems to have no effect on the output
305 * data [I] pointer to data to hash (16 bytes)
306 * output [O] the md4 hash of the data (16 bytes)
309 * Success: STATUS_SUCCESS
310 * Failure: STATUS_UNSUCCESSFUL
314 WINAPI
SystemFunction010(LPVOID unknown
, const BYTE
*data
, LPBYTE hash
)
319 MD4Update( &ctx
, data
, 0x10 );
321 memcpy( hash
, ctx
.digest
, 0x10 );
323 return STATUS_SUCCESS
;
326 /******************************************************************************
327 * SystemFunction012 [ADVAPI32.@]
328 * SystemFunction014 [ADVAPI32.@]
329 * SystemFunction016 [ADVAPI32.@]
330 * SystemFunction018 [ADVAPI32.@]
331 * SystemFunction020 [ADVAPI32.@]
332 * SystemFunction022 [ADVAPI32.@]
334 * Encrypts two DES blocks with two keys
337 * data [I] data to encrypt (16 bytes)
338 * key [I] key data (two lots of 7 bytes)
339 * output [O] buffer to receive encrypted data (16 bytes)
342 * Success: STATUS_SUCCESS
343 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
346 WINAPI
SystemFunction012(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
349 return STATUS_UNSUCCESSFUL
;
351 CRYPT_DEShash(out
, key
, in
);
352 CRYPT_DEShash(out
+8, key
+7, in
+8);
353 return STATUS_SUCCESS
;
356 /******************************************************************************
357 * SystemFunction013 [ADVAPI32.@]
358 * SystemFunction015 [ADVAPI32.@]
359 * SystemFunction017 [ADVAPI32.@]
360 * SystemFunction019 [ADVAPI32.@]
361 * SystemFunction021 [ADVAPI32.@]
362 * SystemFunction023 [ADVAPI32.@]
364 * Decrypts two DES blocks with two keys
367 * data [I] data to decrypt (16 bytes)
368 * key [I] key data (two lots of 7 bytes)
369 * output [O] buffer to receive decrypted data (16 bytes)
372 * Success: STATUS_SUCCESS
373 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
376 WINAPI
SystemFunction013(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
379 return STATUS_UNSUCCESSFUL
;
380 CRYPT_DESunhash(out
, key
, in
);
381 CRYPT_DESunhash(out
+8, key
+7, in
+8);
382 return STATUS_SUCCESS
;
385 /******************************************************************************
386 * SystemFunction024 [ADVAPI32.@]
388 * Encrypts two DES blocks with a 32 bit key...
391 * data [I] data to encrypt (16 bytes)
392 * key [I] key data (4 bytes)
393 * output [O] buffer to receive encrypted data (16 bytes)
396 * Success: STATUS_SUCCESS
399 WINAPI
SystemFunction024(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
403 memcpy(deskey
, key
, 4);
404 memcpy(deskey
+4, key
, 4);
405 memcpy(deskey
+8, key
, 4);
406 memcpy(deskey
+12, key
, 4);
408 CRYPT_DEShash(out
, deskey
, in
);
409 CRYPT_DEShash(out
+8, deskey
+7, in
+8);
411 return STATUS_SUCCESS
;
414 /******************************************************************************
415 * SystemFunction025 [ADVAPI32.@]
417 * Decrypts two DES blocks with a 32 bit key...
420 * data [I] data to encrypt (16 bytes)
421 * key [I] key data (4 bytes)
422 * output [O] buffer to receive encrypted data (16 bytes)
425 * Success: STATUS_SUCCESS
428 WINAPI
SystemFunction025(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
432 memcpy(deskey
, key
, 4);
433 memcpy(deskey
+4, key
, 4);
434 memcpy(deskey
+8, key
, 4);
435 memcpy(deskey
+12, key
, 4);
437 CRYPT_DESunhash(out
, deskey
, in
);
438 CRYPT_DESunhash(out
+8, deskey
+7, in
+8);
440 return STATUS_SUCCESS
;
443 /**********************************************************************
449 SystemFunction028(INT a
, INT b
)
451 //NDRCContextBinding()
452 //SystemFunction034()
453 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
458 /**********************************************************************
464 SystemFunction029(INT a
, INT b
)
466 //I_RpcBindingIsClientLocal()
467 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
472 /******************************************************************************
473 * SystemFunction030 (ADVAPI32.@)
475 * Tests if two blocks of 16 bytes are equal
478 * b1,b2 [I] block of 16 bytes
481 * TRUE if blocks are the same
482 * FALSE if blocks are different
485 WINAPI
SystemFunction030(LPCVOID b1
, LPCVOID b2
)
487 return !memcmp(b1
, b2
, 0x10);
491 /******************************************************************************
492 * SystemFunction032 [ADVAPI32.@]
494 * Encrypts a string data using ARC4
497 * data [I/O] data to encrypt
501 * Success: STATUS_SUCCESS
502 * Failure: STATUS_UNSUCCESSFUL
505 * see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
508 WINAPI
SystemFunction032(struct ustring
*data
, const struct ustring
*key
)
512 rc4_init(&a4i
, key
->Buffer
, key
->Length
);
513 rc4_crypt(&a4i
, data
->Buffer
, data
->Length
);
515 return STATUS_SUCCESS
;
519 /**********************************************************************
525 SystemFunction033(INT a
, INT b
)
527 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
531 /**********************************************************************
537 SystemFunction034(INT a
, INT b
)
539 //RpcBindingToStringBindingW
540 //I_RpcMapWin32Status
541 //RpcStringBindingParseW
543 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
548 /******************************************************************************
549 * SystemFunction035 (ADVAPI32.@)
552 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
555 * Stub, always return TRUE.
557 BOOL WINAPI
SystemFunction035(LPCSTR lpszDllFilePath
)
559 //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
563 /******************************************************************************
564 * SystemFunction036 (ADVAPI32.@)
566 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
569 * pbBuffer [O] Pointer to memory to receive random bytes.
570 * dwLen [I] Number of random bytes to fetch.
573 * Always TRUE in my tests
577 SystemFunction036(PVOID pbBuffer
, ULONG dwLen
)
579 ////////////////////////////////////////////////////////////////
580 //////////////////// B I G W A R N I N G !!! ////////////////
581 // This function will output numbers based on the tick count. //
582 // It will NOT OUPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!! //
583 ////////////////////////////////////////////////////////////////
589 static ULONG uCounter
= 17;
591 if(!pbBuffer
|| !dwLen
)
593 /* This function always returns TRUE, even if invalid parameters were passed. (verified under WinXP SP2) */
597 /* Get the first seed from the performance counter */
598 QueryPerformanceCounter(&time
);
599 dwSeed
= time
.LowPart
^ time
.HighPart
^ RtlUlongByteSwap(uCounter
++);
601 /* We will access the buffer bytewise */
602 pBuffer
= (PBYTE
)pbBuffer
;
606 /* Use the pseudo random number generator RtlRandom, which outputs a 4-byte value and a new seed */
607 uPseudoRandom
= RtlRandom(&dwSeed
);
611 /* Get each byte from the pseudo random number and store it in the buffer */
612 *pBuffer
= (BYTE
)(uPseudoRandom
>> 8 * (dwLen
% 3) & 0xFF);
614 } while(--dwLen
% 3);
620 HANDLE KsecDeviceHandle
;
626 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\KsecDD");
627 OBJECT_ATTRIBUTES ObjectAttributes
;
628 IO_STATUS_BLOCK IoStatusBlock
;
632 InitializeObjectAttributes(&ObjectAttributes
,
634 OBJ_CASE_INSENSITIVE
,
637 Status
= NtOpenFile(&DeviceHandle
,
638 FILE_READ_DATA
| SYNCHRONIZE
,
641 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
642 FILE_SYNCHRONOUS_IO_NONALERT
);
643 if (!NT_SUCCESS(Status
))
648 if (InterlockedCompareExchangePointer(&KsecDeviceHandle
, DeviceHandle
, NULL
) != NULL
)
650 NtClose(DeviceHandle
);
653 return STATUS_SUCCESS
;
657 CloseKsecDdHandle(VOID
)
659 /* Check if we already opened a handle to ksecdd */
660 if (KsecDeviceHandle
!= NULL
)
663 CloseHandle(KsecDeviceHandle
);
664 KsecDeviceHandle
= NULL
;
673 SIZE_T InputBufferLength
,
675 SIZE_T OutputBufferLength
)
677 IO_STATUS_BLOCK IoStatusBlock
;
680 /* Check if we already have a handle */
681 if (KsecDeviceHandle
== NULL
)
683 /* Try to open the device */
684 Status
= KsecOpenDevice();
685 if (!NT_SUCCESS(Status
))
687 //ERR("Failed to open handle to KsecDd driver!\n");
692 /* Call the driver */
693 Status
= NtDeviceIoControlFile(KsecDeviceHandle
,
708 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
712 /******************************************************************************
713 * SystemFunction040 (ADVAPI32.@)
715 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
718 * memory [I/O] Pointer to memory to encrypt.
719 * length [I] Length of region to encrypt in bytes.
720 * flags [I] Control whether other processes are able to decrypt the memory.
721 * RTL_ENCRYPT_OPTION_SAME_PROCESS
722 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
723 * RTL_ENCRYPT_OPTION_SAME_LOGON
726 * Success: STATUS_SUCCESS
727 * Failure: NTSTATUS error code
730 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
731 * If flags are specified when encrypting, the same flag value must be given
732 * when decrypting the memory.
737 _Inout_ PVOID Memory
,
738 _In_ ULONG MemoryLength
,
739 _In_ ULONG OptionFlags
)
743 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
745 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_PROCESS
;
747 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
749 IoControlCode
= IOCTL_KSEC_ENCRYPT_CROSS_PROCESS
;
751 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
753 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_LOGON
;
757 return STATUS_INVALID_PARAMETER
;
760 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);
763 /******************************************************************************
764 * SystemFunction041 (ADVAPI32.@)
766 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
769 * memory [I/O] Pointer to memory to decrypt.
770 * length [I] Length of region to decrypt in bytes.
771 * flags [I] Control whether other processes are able to decrypt the memory.
772 * RTL_ENCRYPT_OPTION_SAME_PROCESS
773 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
774 * RTL_ENCRYPT_OPTION_SAME_LOGON
777 * Success: STATUS_SUCCESS
778 * Failure: NTSTATUS error code
781 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
782 * If flags are specified when encrypting, the same flag value must be given
783 * when decrypting the memory.
788 _Inout_ PVOID Memory
,
789 _In_ ULONG MemoryLength
,
790 _In_ ULONG OptionFlags
)
794 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
796 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_PROCESS
;
798 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
800 IoControlCode
= IOCTL_KSEC_DECRYPT_CROSS_PROCESS
;
802 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
804 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_LOGON
;
808 return STATUS_INVALID_PARAMETER
;
811 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);