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
10 * 20080424 Ported from WINE
15 #include <ksecioctl.h>
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', '!', '@', '#'};
25 /******************************************************************************
26 * SystemFunction001 [ADVAPI32.@]
28 * Encrypts a single block of data using DES
31 * data [I] data to encrypt (8 bytes)
32 * key [I] key data (7 bytes)
33 * output [O] the encrypted data (8 bytes)
36 * Success: STATUS_SUCCESS
37 * Failure: STATUS_UNSUCCESSFUL
41 WINAPI
SystemFunction001(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
44 return STATUS_UNSUCCESSFUL
;
45 CRYPT_DEShash(output
, key
, data
);
46 return STATUS_SUCCESS
;
50 /******************************************************************************
51 * SystemFunction002 [ADVAPI32.@]
53 * Decrypts a single block of data using DES
56 * data [I] data to decrypt (8 bytes)
57 * key [I] key data (7 bytes)
58 * output [O] the decrypted data (8 bytes)
61 * Success: STATUS_SUCCESS
62 * Failure: STATUS_UNSUCCESSFUL
66 WINAPI
SystemFunction002(const BYTE
*data
, const BYTE
*key
, LPBYTE output
)
69 return STATUS_UNSUCCESSFUL
;
70 CRYPT_DESunhash(output
, key
, data
);
71 return STATUS_SUCCESS
;
75 /******************************************************************************
76 * SystemFunction003 [ADVAPI32.@]
78 * Hashes a key using DES and a fixed datablock
81 * key [I] key data (7 bytes)
82 * output [O] hashed key (8 bytes)
85 * Success: STATUS_SUCCESS
86 * Failure: STATUS_UNSUCCESSFUL
90 WINAPI
SystemFunction003(const BYTE
*key
, LPBYTE output
)
93 return STATUS_UNSUCCESSFUL
;
94 CRYPT_DEShash(output
, key
, CRYPT_LMhash_Magic
);
95 return STATUS_SUCCESS
;
99 /******************************************************************************
100 * SystemFunction004 [ADVAPI32.@]
102 * Encrypts a block of data with DES in ECB mode, preserving the length
105 * data [I] data to encrypt
106 * key [I] key data (up to 7 bytes)
107 * output [O] buffer to receive encrypted data
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
115 * Encrypt buffer size should be input size rounded up to 8 bytes
116 * plus an extra 8 bytes.
119 WINAPI
SystemFunction004(const struct ustring
*in
,
120 const struct ustring
*key
,
127 unsigned char deskey
[7];
128 unsigned int crypt_len
, ofs
;
131 return STATUS_INVALID_PARAMETER_2
;
133 crypt_len
= ((in
->Length
+7)&~7);
134 if (out
->MaximumLength
< (crypt_len
+8))
136 out
->Length
= crypt_len
+ 8;
137 return STATUS_BUFFER_TOO_SMALL
;
140 data
.ui
[0] = in
->Length
;
143 if (key
->Length
<sizeof deskey
)
145 memset(deskey
, 0, sizeof deskey
);
146 memcpy(deskey
, key
->Buffer
, key
->Length
);
149 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
151 CRYPT_DEShash(out
->Buffer
, deskey
, data
.uc
);
153 for(ofs
=0; ofs
<(crypt_len
-8); ofs
+=8)
154 CRYPT_DEShash(out
->Buffer
+8+ofs
, deskey
, in
->Buffer
+ofs
);
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
);
160 out
->Length
= crypt_len
+8;
162 return STATUS_SUCCESS
;
165 /******************************************************************************
166 * SystemFunction005 [ADVAPI32.@]
168 * Decrypts a block of data with DES in ECB mode
171 * data [I] data to decrypt
172 * key [I] key data (up to 7 bytes)
173 * output [O] buffer to receive decrypted data
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
182 WINAPI
SystemFunction005(const struct ustring
*in
,
183 const struct ustring
*key
,
190 unsigned char deskey
[7];
191 unsigned int ofs
, crypt_len
;
194 return STATUS_INVALID_PARAMETER_2
;
196 if (key
->Length
<sizeof deskey
)
198 memset(deskey
, 0, sizeof deskey
);
199 memcpy(deskey
, key
->Buffer
, key
->Length
);
202 memcpy(deskey
, key
->Buffer
, sizeof deskey
);
204 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
);
207 return STATUS_UNKNOWN_REVISION
;
209 crypt_len
= data
.ui
[0];
210 if (crypt_len
> out
->MaximumLength
)
212 out
->Length
= crypt_len
;
213 return STATUS_BUFFER_TOO_SMALL
;
216 for (ofs
=0; (ofs
+8)<crypt_len
; ofs
+=8)
217 CRYPT_DESunhash(out
->Buffer
+ofs
, deskey
, in
->Buffer
+ofs
+8);
221 CRYPT_DESunhash(data
.uc
, deskey
, in
->Buffer
+ofs
+8);
222 memcpy(out
->Buffer
+ofs
, data
.uc
, crypt_len
-ofs
);
225 out
->Length
= crypt_len
;
227 return STATUS_SUCCESS
;
230 /******************************************************************************
231 * SystemFunction007 [ADVAPI32.@]
233 * MD4 hash a unicode string
236 * string [I] the string to hash
237 * output [O] the md4 hash of the string (16 bytes)
240 * Success: STATUS_SUCCESS
241 * Failure: STATUS_UNSUCCESSFUL
245 WINAPI
SystemFunction007(const UNICODE_STRING
*string
, LPBYTE hash
)
250 MD4Update( &ctx
, (const BYTE
*)string
->Buffer
, string
->Length
);
252 memcpy( hash
, ctx
.digest
, 0x10 );
254 return STATUS_SUCCESS
;
257 /******************************************************************************
258 * SystemFunction008 [ADVAPI32.@]
260 * Creates a LM response from a challenge and a password hash
263 * challenge [I] Challenge from authentication server
264 * hash [I] NTLM hash (from SystemFunction006)
265 * response [O] response to send back to the server
268 * Success: STATUS_SUCCESS
269 * Failure: STATUS_UNSUCCESSFUL
272 * see http://davenport.sourceforge.net/ntlm.html#theLmResponse
276 WINAPI
SystemFunction008(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
280 if (!challenge
|| !response
)
281 return STATUS_UNSUCCESSFUL
;
283 memset(key
, 0, sizeof key
);
284 memcpy(key
, hash
, 0x10);
286 CRYPT_DEShash(response
, key
, challenge
);
287 CRYPT_DEShash(response
+8, key
+7, challenge
);
288 CRYPT_DEShash(response
+16, key
+14, challenge
);
290 return STATUS_SUCCESS
;
293 /******************************************************************************
294 * SystemFunction009 [ADVAPI32.@]
296 * Seems to do the same as SystemFunction008...
299 WINAPI
SystemFunction009(const BYTE
*challenge
, const BYTE
*hash
, LPBYTE response
)
301 return SystemFunction008(challenge
, hash
, response
);
304 /******************************************************************************
305 * SystemFunction010 [ADVAPI32.@]
306 * SystemFunction011 [ADVAPI32.@]
308 * MD4 hashes 16 bytes of data
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)
316 * Success: STATUS_SUCCESS
317 * Failure: STATUS_UNSUCCESSFUL
321 WINAPI
SystemFunction010(LPVOID unknown
, const BYTE
*data
, LPBYTE hash
)
326 MD4Update( &ctx
, data
, 0x10 );
328 memcpy( hash
, ctx
.digest
, 0x10 );
330 return STATUS_SUCCESS
;
333 /******************************************************************************
334 * SystemFunction012 [ADVAPI32.@]
335 * SystemFunction014 [ADVAPI32.@]
336 * SystemFunction016 [ADVAPI32.@]
337 * SystemFunction018 [ADVAPI32.@]
338 * SystemFunction020 [ADVAPI32.@]
339 * SystemFunction022 [ADVAPI32.@]
341 * Encrypts two DES blocks with two keys
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)
349 * Success: STATUS_SUCCESS
350 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
353 WINAPI
SystemFunction012(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
356 return STATUS_UNSUCCESSFUL
;
358 CRYPT_DEShash(out
, key
, in
);
359 CRYPT_DEShash(out
+8, key
+7, in
+8);
360 return STATUS_SUCCESS
;
363 /******************************************************************************
364 * SystemFunction013 [ADVAPI32.@]
365 * SystemFunction015 [ADVAPI32.@]
366 * SystemFunction017 [ADVAPI32.@]
367 * SystemFunction019 [ADVAPI32.@]
368 * SystemFunction021 [ADVAPI32.@]
369 * SystemFunction023 [ADVAPI32.@]
371 * Decrypts two DES blocks with two keys
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)
379 * Success: STATUS_SUCCESS
380 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
383 WINAPI
SystemFunction013(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
386 return STATUS_UNSUCCESSFUL
;
387 CRYPT_DESunhash(out
, key
, in
);
388 CRYPT_DESunhash(out
+8, key
+7, in
+8);
389 return STATUS_SUCCESS
;
392 /******************************************************************************
393 * SystemFunction024 [ADVAPI32.@]
395 * Encrypts two DES blocks with a 32 bit key...
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)
403 * Success: STATUS_SUCCESS
406 WINAPI
SystemFunction024(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
410 memcpy(deskey
, key
, 4);
411 memcpy(deskey
+4, key
, 4);
412 memcpy(deskey
+8, key
, 4);
413 memcpy(deskey
+12, key
, 4);
415 CRYPT_DEShash(out
, deskey
, in
);
416 CRYPT_DEShash(out
+8, deskey
+7, in
+8);
418 return STATUS_SUCCESS
;
421 /******************************************************************************
422 * SystemFunction025 [ADVAPI32.@]
424 * Decrypts two DES blocks with a 32 bit key...
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)
432 * Success: STATUS_SUCCESS
435 WINAPI
SystemFunction025(const BYTE
*in
, const BYTE
*key
, LPBYTE out
)
439 memcpy(deskey
, key
, 4);
440 memcpy(deskey
+4, key
, 4);
441 memcpy(deskey
+8, key
, 4);
442 memcpy(deskey
+12, key
, 4);
444 CRYPT_DESunhash(out
, deskey
, in
);
445 CRYPT_DESunhash(out
+8, deskey
+7, in
+8);
447 return STATUS_SUCCESS
;
450 /**********************************************************************
451 * SystemFunction028 [ADVAPI32.@]
453 * Retrieves an encryption session key...
456 * ContextHandle [I] RPC context handle
457 * SessionKey [O] buffer to receive the session key (16 bytes)
460 * Success: STATUS_LOCAL_USER_SESSION_KEY
467 _In_ PVOID ContextHandle
,
468 _Out_ LPBYTE SessionKey
)
470 /* HACK: Always return the default key */
471 memcpy(SessionKey
, DefaultSessionKey
, sizeof(DefaultSessionKey
));
472 return STATUS_LOCAL_USER_SESSION_KEY
;
475 //NDRCContextBinding();
476 //SystemFunction034()
477 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
483 /**********************************************************************
489 SystemFunction029(INT a
, INT b
)
491 //I_RpcBindingIsClientLocal()
492 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
497 /******************************************************************************
498 * SystemFunction030 (ADVAPI32.@)
500 * Tests if two blocks of 16 bytes are equal
503 * b1,b2 [I] block of 16 bytes
506 * TRUE if blocks are the same
507 * FALSE if blocks are different
510 WINAPI
SystemFunction030(LPCVOID b1
, LPCVOID b2
)
512 return !memcmp(b1
, b2
, 0x10);
516 /******************************************************************************
517 * SystemFunction032 [ADVAPI32.@]
519 * Encrypts a string data using ARC4
522 * data [I/O] data to encrypt
526 * Success: STATUS_SUCCESS
527 * Failure: STATUS_UNSUCCESSFUL
530 * see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
533 WINAPI
SystemFunction032(struct ustring
*data
, const struct ustring
*key
)
537 rc4_init(&a4i
, key
->Buffer
, key
->Length
);
538 rc4_crypt(&a4i
, data
->Buffer
, data
->Length
);
540 return STATUS_SUCCESS
;
544 /**********************************************************************
550 SystemFunction033(INT a
, INT b
)
552 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
556 /**********************************************************************
562 SystemFunction034(INT a
, INT b
)
564 //RpcBindingToStringBindingW
565 //I_RpcMapWin32Status
566 //RpcStringBindingParseW
568 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
573 /******************************************************************************
574 * SystemFunction035 (ADVAPI32.@)
577 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
580 * Stub, always return TRUE.
582 BOOL WINAPI
SystemFunction035(LPCSTR lpszDllFilePath
)
584 //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
588 /******************************************************************************
589 * SystemFunction036 (ADVAPI32.@)
591 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
594 * pbBuffer [O] Pointer to memory to receive random bytes.
595 * dwLen [I] Number of random bytes to fetch.
598 * Always TRUE in my tests
602 SystemFunction036(PVOID pbBuffer
, ULONG dwLen
)
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 ////////////////////////////////////////////////////////////////
614 static ULONG uCounter
= 17;
616 if(!pbBuffer
|| !dwLen
)
618 /* This function always returns TRUE, even if invalid parameters were passed. (verified under WinXP SP2) */
622 /* Get the first seed from the performance counter */
623 QueryPerformanceCounter(&time
);
624 dwSeed
= time
.LowPart
^ time
.HighPart
^ RtlUlongByteSwap(uCounter
++);
626 /* We will access the buffer bytewise */
627 pBuffer
= (PBYTE
)pbBuffer
;
631 /* Use the pseudo random number generator RtlRandom, which outputs a 4-byte value and a new seed */
632 uPseudoRandom
= RtlRandom(&dwSeed
);
636 /* Get each byte from the pseudo random number and store it in the buffer */
637 *pBuffer
= (BYTE
)(uPseudoRandom
>> 8 * (dwLen
% 3) & 0xFF);
639 } while(--dwLen
% 3);
645 HANDLE KsecDeviceHandle
;
651 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\KsecDD");
652 OBJECT_ATTRIBUTES ObjectAttributes
;
653 IO_STATUS_BLOCK IoStatusBlock
;
657 InitializeObjectAttributes(&ObjectAttributes
,
659 OBJ_CASE_INSENSITIVE
,
662 Status
= NtOpenFile(&DeviceHandle
,
663 FILE_READ_DATA
| SYNCHRONIZE
,
666 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
667 FILE_SYNCHRONOUS_IO_NONALERT
);
668 if (!NT_SUCCESS(Status
))
673 if (InterlockedCompareExchangePointer(&KsecDeviceHandle
, DeviceHandle
, NULL
) != NULL
)
675 NtClose(DeviceHandle
);
678 return STATUS_SUCCESS
;
682 CloseKsecDdHandle(VOID
)
684 /* Check if we already opened a handle to ksecdd */
685 if (KsecDeviceHandle
!= NULL
)
688 CloseHandle(KsecDeviceHandle
);
689 KsecDeviceHandle
= NULL
;
698 SIZE_T InputBufferLength
,
700 SIZE_T OutputBufferLength
)
702 IO_STATUS_BLOCK IoStatusBlock
;
705 /* Check if we already have a handle */
706 if (KsecDeviceHandle
== NULL
)
708 /* Try to open the device */
709 Status
= KsecOpenDevice();
710 if (!NT_SUCCESS(Status
))
712 //ERR("Failed to open handle to KsecDd driver!\n");
717 /* Call the driver */
718 Status
= NtDeviceIoControlFile(KsecDeviceHandle
,
733 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
737 /******************************************************************************
738 * SystemFunction040 (ADVAPI32.@)
740 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
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
751 * Success: STATUS_SUCCESS
752 * Failure: NTSTATUS error code
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.
762 _Inout_ PVOID Memory
,
763 _In_ ULONG MemoryLength
,
764 _In_ ULONG OptionFlags
)
768 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
770 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_PROCESS
;
772 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
774 IoControlCode
= IOCTL_KSEC_ENCRYPT_CROSS_PROCESS
;
776 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
778 IoControlCode
= IOCTL_KSEC_ENCRYPT_SAME_LOGON
;
782 return STATUS_INVALID_PARAMETER
;
785 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);
788 /******************************************************************************
789 * SystemFunction041 (ADVAPI32.@)
791 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
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
802 * Success: STATUS_SUCCESS
803 * Failure: NTSTATUS error code
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.
813 _Inout_ PVOID Memory
,
814 _In_ ULONG MemoryLength
,
815 _In_ ULONG OptionFlags
)
819 if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_PROCESS
)
821 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_PROCESS
;
823 else if (OptionFlags
== RTL_ENCRYPT_OPTION_CROSS_PROCESS
)
825 IoControlCode
= IOCTL_KSEC_DECRYPT_CROSS_PROCESS
;
827 else if (OptionFlags
== RTL_ENCRYPT_OPTION_SAME_LOGON
)
829 IoControlCode
= IOCTL_KSEC_DECRYPT_SAME_LOGON
;
833 return STATUS_INVALID_PARAMETER
;
836 return KsecDeviceIoControl(IoControlCode
, Memory
, MemoryLength
, Memory
, MemoryLength
);