[SHELL-EXPERIMENTS]
[reactos.git] / dll / win32 / advapi32 / misc / sysfunc.c
1 /*
2 *
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
8 * UPDATE HISTORY:
9 * 19990413 EA created
10 * 19990415 EA
11 * 20080424 Ported from WINE
12 */
13
14 #include <advapi32.h>
15 #include <md4.h>
16 #include <md5.h>
17 #include <rc4.h>
18
19 static const unsigned char CRYPT_LMhash_Magic[8] =
20 { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
21
22 /******************************************************************************
23 * SystemFunction001 [ADVAPI32.@]
24 *
25 * Encrypts a single block of data using DES
26 *
27 * PARAMS
28 * data [I] data to encrypt (8 bytes)
29 * key [I] key data (7 bytes)
30 * output [O] the encrypted data (8 bytes)
31 *
32 * RETURNS
33 * Success: STATUS_SUCCESS
34 * Failure: STATUS_UNSUCCESSFUL
35 *
36 */
37 NTSTATUS
38 WINAPI SystemFunction001(const BYTE *data, const BYTE *key, LPBYTE output)
39 {
40 if (!data || !output)
41 return STATUS_UNSUCCESSFUL;
42 CRYPT_DEShash(output, key, data);
43 return STATUS_SUCCESS;
44 }
45
46
47 /******************************************************************************
48 * SystemFunction002 [ADVAPI32.@]
49 *
50 * Decrypts a single block of data using DES
51 *
52 * PARAMS
53 * data [I] data to decrypt (8 bytes)
54 * key [I] key data (7 bytes)
55 * output [O] the decrypted data (8 bytes)
56 *
57 * RETURNS
58 * Success: STATUS_SUCCESS
59 * Failure: STATUS_UNSUCCESSFUL
60 *
61 */
62 NTSTATUS
63 WINAPI SystemFunction002(const BYTE *data, const BYTE *key, LPBYTE output)
64 {
65 if (!data || !output)
66 return STATUS_UNSUCCESSFUL;
67 CRYPT_DESunhash(output, key, data);
68 return STATUS_SUCCESS;
69 }
70
71
72 /******************************************************************************
73 * SystemFunction003 [ADVAPI32.@]
74 *
75 * Hashes a key using DES and a fixed datablock
76 *
77 * PARAMS
78 * key [I] key data (7 bytes)
79 * output [O] hashed key (8 bytes)
80 *
81 * RETURNS
82 * Success: STATUS_SUCCESS
83 * Failure: STATUS_UNSUCCESSFUL
84 *
85 */
86 NTSTATUS
87 WINAPI SystemFunction003(const BYTE *key, LPBYTE output)
88 {
89 if (!output)
90 return STATUS_UNSUCCESSFUL;
91 CRYPT_DEShash(output, key, CRYPT_LMhash_Magic);
92 return STATUS_SUCCESS;
93 }
94
95
96 /******************************************************************************
97 * SystemFunction004 [ADVAPI32.@]
98 *
99 * Encrypts a block of data with DES in ECB mode, preserving the length
100 *
101 * PARAMS
102 * data [I] data to encrypt
103 * key [I] key data (up to 7 bytes)
104 * output [O] buffer to receive encrypted data
105 *
106 * RETURNS
107 * Success: STATUS_SUCCESS
108 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
109 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
110 *
111 * NOTES
112 * Encrypt buffer size should be input size rounded up to 8 bytes
113 * plus an extra 8 bytes.
114 */
115 NTSTATUS
116 WINAPI SystemFunction004(const struct ustring *in,
117 const struct ustring *key,
118 struct ustring *out)
119 {
120 union {
121 unsigned char uc[8];
122 unsigned int ui[2];
123 } data;
124 unsigned char deskey[7];
125 unsigned int crypt_len, ofs;
126
127 if (key->Length<=0)
128 return STATUS_INVALID_PARAMETER_2;
129
130 crypt_len = ((in->Length+7)&~7);
131 if (out->MaximumLength < (crypt_len+8))
132 return STATUS_BUFFER_TOO_SMALL;
133
134 data.ui[0] = in->Length;
135 data.ui[1] = 1;
136
137 if (key->Length<sizeof deskey)
138 {
139 memset(deskey, 0, sizeof deskey);
140 memcpy(deskey, key->Buffer, key->Length);
141 }
142 else
143 memcpy(deskey, key->Buffer, sizeof deskey);
144
145 CRYPT_DEShash(out->Buffer, deskey, data.uc);
146
147 for(ofs=0; ofs<(crypt_len-8); ofs+=8)
148 CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs);
149
150 memset(data.uc, 0, sizeof data.uc);
151 memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len);
152 CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc);
153
154 out->Length = crypt_len+8;
155
156 return STATUS_SUCCESS;
157 }
158
159 /******************************************************************************
160 * SystemFunction005 [ADVAPI32.@]
161 *
162 * Decrypts a block of data with DES in ECB mode
163 *
164 * PARAMS
165 * data [I] data to decrypt
166 * key [I] key data (up to 7 bytes)
167 * output [O] buffer to receive decrypted data
168 *
169 * RETURNS
170 * Success: STATUS_SUCCESS
171 * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small
172 * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length
173 *
174 */
175 NTSTATUS
176 WINAPI SystemFunction005(const struct ustring *in,
177 const struct ustring *key,
178 struct ustring *out)
179 {
180 union {
181 unsigned char uc[8];
182 unsigned int ui[2];
183 } data;
184 unsigned char deskey[7];
185 unsigned int ofs, crypt_len;
186
187 if (key->Length<=0)
188 return STATUS_INVALID_PARAMETER_2;
189
190 if (key->Length<sizeof deskey)
191 {
192 memset(deskey, 0, sizeof deskey);
193 memcpy(deskey, key->Buffer, key->Length);
194 }
195 else
196 memcpy(deskey, key->Buffer, sizeof deskey);
197
198 CRYPT_DESunhash(data.uc, deskey, in->Buffer);
199
200 if (data.ui[1] != 1)
201 return STATUS_UNKNOWN_REVISION;
202
203 crypt_len = data.ui[0];
204 if (crypt_len > out->MaximumLength)
205 return STATUS_BUFFER_TOO_SMALL;
206
207 for (ofs=0; (ofs+8)<crypt_len; ofs+=8)
208 CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8);
209
210 if (ofs<crypt_len)
211 {
212 CRYPT_DESunhash(data.uc, deskey, in->Buffer+ofs+8);
213 memcpy(out->Buffer+ofs, data.uc, crypt_len-ofs);
214 }
215
216 out->Length = crypt_len;
217
218 return STATUS_SUCCESS;
219 }
220
221 /******************************************************************************
222 * SystemFunction007 [ADVAPI32.@]
223 *
224 * MD4 hash a unicode string
225 *
226 * PARAMS
227 * string [I] the string to hash
228 * output [O] the md4 hash of the string (16 bytes)
229 *
230 * RETURNS
231 * Success: STATUS_SUCCESS
232 * Failure: STATUS_UNSUCCESSFUL
233 *
234 */
235 NTSTATUS
236 WINAPI SystemFunction007(const UNICODE_STRING *string, LPBYTE hash)
237 {
238 MD4_CTX ctx;
239
240 MD4Init( &ctx );
241 MD4Update( &ctx, (const BYTE *)string->Buffer, string->Length );
242 MD4Final( &ctx );
243 memcpy( hash, ctx.digest, 0x10 );
244
245 return STATUS_SUCCESS;
246 }
247
248 /******************************************************************************
249 * SystemFunction008 [ADVAPI32.@]
250 *
251 * Creates a LM response from a challenge and a password hash
252 *
253 * PARAMS
254 * challenge [I] Challenge from authentication server
255 * hash [I] NTLM hash (from SystemFunction006)
256 * response [O] response to send back to the server
257 *
258 * RETURNS
259 * Success: STATUS_SUCCESS
260 * Failure: STATUS_UNSUCCESSFUL
261 *
262 * NOTES
263 * see http://davenport.sourceforge.net/ntlm.html#theLmResponse
264 *
265 */
266 NTSTATUS
267 WINAPI SystemFunction008(const BYTE *challenge, const BYTE *hash, LPBYTE response)
268 {
269 BYTE key[7*3];
270
271 if (!challenge || !response)
272 return STATUS_UNSUCCESSFUL;
273
274 memset(key, 0, sizeof key);
275 memcpy(key, hash, 0x10);
276
277 CRYPT_DEShash(response, key, challenge);
278 CRYPT_DEShash(response+8, key+7, challenge);
279 CRYPT_DEShash(response+16, key+14, challenge);
280
281 return STATUS_SUCCESS;
282 }
283
284 /******************************************************************************
285 * SystemFunction009 [ADVAPI32.@]
286 *
287 * Seems to do the same as SystemFunction008...
288 */
289 NTSTATUS
290 WINAPI SystemFunction009(const BYTE *challenge, const BYTE *hash, LPBYTE response)
291 {
292 return SystemFunction008(challenge, hash, response);
293 }
294
295 /******************************************************************************
296 * SystemFunction010 [ADVAPI32.@]
297 * SystemFunction011 [ADVAPI32.@]
298 *
299 * MD4 hashes 16 bytes of data
300 *
301 * PARAMS
302 * unknown [] seems to have no effect on the output
303 * data [I] pointer to data to hash (16 bytes)
304 * output [O] the md4 hash of the data (16 bytes)
305 *
306 * RETURNS
307 * Success: STATUS_SUCCESS
308 * Failure: STATUS_UNSUCCESSFUL
309 *
310 */
311 NTSTATUS
312 WINAPI SystemFunction010(LPVOID unknown, const BYTE *data, LPBYTE hash)
313 {
314 MD4_CTX ctx;
315
316 MD4Init( &ctx );
317 MD4Update( &ctx, data, 0x10 );
318 MD4Final( &ctx );
319 memcpy( hash, ctx.digest, 0x10 );
320
321 return STATUS_SUCCESS;
322 }
323
324 /******************************************************************************
325 * SystemFunction012 [ADVAPI32.@]
326 * SystemFunction014 [ADVAPI32.@]
327 * SystemFunction016 [ADVAPI32.@]
328 * SystemFunction018 [ADVAPI32.@]
329 * SystemFunction020 [ADVAPI32.@]
330 * SystemFunction022 [ADVAPI32.@]
331 *
332 * Encrypts two DES blocks with two keys
333 *
334 * PARAMS
335 * data [I] data to encrypt (16 bytes)
336 * key [I] key data (two lots of 7 bytes)
337 * output [O] buffer to receive encrypted data (16 bytes)
338 *
339 * RETURNS
340 * Success: STATUS_SUCCESS
341 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
342 */
343 NTSTATUS
344 WINAPI SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out)
345 {
346 if (!in || !out)
347 return STATUS_UNSUCCESSFUL;
348
349 CRYPT_DEShash(out, key, in);
350 CRYPT_DEShash(out+8, key+7, in+8);
351 return STATUS_SUCCESS;
352 }
353
354 /******************************************************************************
355 * SystemFunction013 [ADVAPI32.@]
356 * SystemFunction015 [ADVAPI32.@]
357 * SystemFunction017 [ADVAPI32.@]
358 * SystemFunction019 [ADVAPI32.@]
359 * SystemFunction021 [ADVAPI32.@]
360 * SystemFunction023 [ADVAPI32.@]
361 *
362 * Decrypts two DES blocks with two keys
363 *
364 * PARAMS
365 * data [I] data to decrypt (16 bytes)
366 * key [I] key data (two lots of 7 bytes)
367 * output [O] buffer to receive decrypted data (16 bytes)
368 *
369 * RETURNS
370 * Success: STATUS_SUCCESS
371 * Failure: STATUS_UNSUCCESSFUL if the input or output buffer is NULL
372 */
373 NTSTATUS
374 WINAPI SystemFunction013(const BYTE *in, const BYTE *key, LPBYTE out)
375 {
376 if (!in || !out)
377 return STATUS_UNSUCCESSFUL;
378 CRYPT_DESunhash(out, key, in);
379 CRYPT_DESunhash(out+8, key+7, in+8);
380 return STATUS_SUCCESS;
381 }
382
383 /******************************************************************************
384 * SystemFunction024 [ADVAPI32.@]
385 *
386 * Encrypts two DES blocks with a 32 bit key...
387 *
388 * PARAMS
389 * data [I] data to encrypt (16 bytes)
390 * key [I] key data (4 bytes)
391 * output [O] buffer to receive encrypted data (16 bytes)
392 *
393 * RETURNS
394 * Success: STATUS_SUCCESS
395 */
396 NTSTATUS
397 WINAPI SystemFunction024(const BYTE *in, const BYTE *key, LPBYTE out)
398 {
399 BYTE deskey[0x10];
400
401 memcpy(deskey, key, 4);
402 memcpy(deskey+4, key, 4);
403 memcpy(deskey+8, key, 4);
404 memcpy(deskey+12, key, 4);
405
406 CRYPT_DEShash(out, deskey, in);
407 CRYPT_DEShash(out+8, deskey+7, in+8);
408
409 return STATUS_SUCCESS;
410 }
411
412 /******************************************************************************
413 * SystemFunction025 [ADVAPI32.@]
414 *
415 * Decrypts two DES blocks with a 32 bit key...
416 *
417 * PARAMS
418 * data [I] data to encrypt (16 bytes)
419 * key [I] key data (4 bytes)
420 * output [O] buffer to receive encrypted data (16 bytes)
421 *
422 * RETURNS
423 * Success: STATUS_SUCCESS
424 */
425 NTSTATUS
426 WINAPI SystemFunction025(const BYTE *in, const BYTE *key, LPBYTE out)
427 {
428 BYTE deskey[0x10];
429
430 memcpy(deskey, key, 4);
431 memcpy(deskey+4, key, 4);
432 memcpy(deskey+8, key, 4);
433 memcpy(deskey+12, key, 4);
434
435 CRYPT_DESunhash(out, deskey, in);
436 CRYPT_DESunhash(out+8, deskey+7, in+8);
437
438 return STATUS_SUCCESS;
439 }
440
441 /**********************************************************************
442 *
443 * @unimplemented
444 */
445 INT
446 WINAPI
447 SystemFunction028(INT a, INT b)
448 {
449 //NDRCContextBinding()
450 //SystemFunction034()
451 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
452 return 28;
453 }
454
455
456 /**********************************************************************
457 *
458 * @unimplemented
459 */
460 INT
461 WINAPI
462 SystemFunction029(INT a, INT b)
463 {
464 //I_RpcBindingIsClientLocal()
465 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
466 return 29;
467 }
468
469
470 /******************************************************************************
471 * SystemFunction030 (ADVAPI32.@)
472 *
473 * Tests if two blocks of 16 bytes are equal
474 *
475 * PARAMS
476 * b1,b2 [I] block of 16 bytes
477 *
478 * RETURNS
479 * TRUE if blocks are the same
480 * FALSE if blocks are different
481 */
482 BOOL
483 WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
484 {
485 return !memcmp(b1, b2, 0x10);
486 }
487
488
489 /******************************************************************************
490 * SystemFunction032 [ADVAPI32.@]
491 *
492 * Encrypts a string data using ARC4
493 *
494 * PARAMS
495 * data [I/O] data to encrypt
496 * key [I] key data
497 *
498 * RETURNS
499 * Success: STATUS_SUCCESS
500 * Failure: STATUS_UNSUCCESSFUL
501 *
502 * NOTES
503 * see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
504 */
505 NTSTATUS
506 WINAPI SystemFunction032(struct ustring *data, const struct ustring *key)
507 {
508 RC4_CONTEXT a4i;
509
510 rc4_init(&a4i, key->Buffer, key->Length);
511 rc4_crypt(&a4i, data->Buffer, data->Length);
512
513 return STATUS_SUCCESS;
514 }
515
516
517 /**********************************************************************
518 *
519 * @unimplemented
520 */
521 INT
522 WINAPI
523 SystemFunction033(INT a, INT b)
524 {
525 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
526 return 33;
527 }
528
529 /**********************************************************************
530 *
531 * @unimplemented
532 */
533 INT
534 WINAPI
535 SystemFunction034(INT a, INT b)
536 {
537 //RpcBindingToStringBindingW
538 //I_RpcMapWin32Status
539 //RpcStringBindingParseW
540 //RpcStringFreeW
541 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
542 return 34;
543 }
544
545
546 /******************************************************************************
547 * SystemFunction035 (ADVAPI32.@)
548 *
549 * Described here:
550 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
551 *
552 * NOTES
553 * Stub, always return TRUE.
554 */
555 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
556 {
557 //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
558 return TRUE;
559 }
560
561 /******************************************************************************
562 * SystemFunction036 (ADVAPI32.@)
563 *
564 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
565 *
566 * PARAMS
567 * pbBuffer [O] Pointer to memory to receive random bytes.
568 * dwLen [I] Number of random bytes to fetch.
569 *
570 * RETURNS
571 * Always TRUE in my tests
572 */
573 BOOLEAN
574 WINAPI
575 SystemFunction036(PVOID pbBuffer, ULONG dwLen)
576 {
577 ////////////////////////////////////////////////////////////////
578 //////////////////// B I G W A R N I N G !!! ////////////////
579 // This function will output numbers based on the tick count. //
580 // It will NOT OUPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!! //
581 ////////////////////////////////////////////////////////////////
582
583 DWORD dwSeed;
584 PBYTE pBuffer;
585 ULONG uPseudoRandom;
586 LARGE_INTEGER time;
587 static ULONG uCounter = 17;
588
589 if(!pbBuffer || !dwLen)
590 {
591 /* This function always returns TRUE, even if invalid parameters were passed. (verified under WinXP SP2) */
592 return TRUE;
593 }
594
595 /* Get the first seed from the performance counter */
596 QueryPerformanceCounter(&time);
597 dwSeed = time.LowPart ^ time.HighPart ^ RtlUlongByteSwap(uCounter++);
598
599 /* We will access the buffer bytewise */
600 pBuffer = (PBYTE)pbBuffer;
601
602 do
603 {
604 /* Use the pseudo random number generator RtlRandom, which outputs a 4-byte value and a new seed */
605 uPseudoRandom = RtlRandom(&dwSeed);
606
607 do
608 {
609 /* Get each byte from the pseudo random number and store it in the buffer */
610 *pBuffer = (BYTE)(uPseudoRandom >> 8 * (dwLen % 3) & 0xFF);
611 ++pBuffer;
612 } while(--dwLen % 3);
613 } while(dwLen);
614
615 return TRUE;
616 }
617
618 /*
619 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
620 in crypt32.dll.
621 */
622
623 /******************************************************************************
624 * SystemFunction040 (ADVAPI32.@)
625 *
626 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
627 *
628 * PARAMS
629 * memory [I/O] Pointer to memory to encrypt.
630 * length [I] Length of region to encrypt in bytes.
631 * flags [I] Control whether other processes are able to decrypt the memory.
632 * RTL_ENCRYPT_OPTION_SAME_PROCESS
633 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
634 * RTL_ENCRYPT_OPTION_SAME_LOGON
635 *
636 * RETURNS
637 * Success: STATUS_SUCCESS
638 * Failure: NTSTATUS error code
639 *
640 * NOTES
641 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
642 * If flags are specified when encrypting, the same flag value must be given
643 * when decrypting the memory.
644 */
645 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
646 {
647 //FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
648 return STATUS_SUCCESS;
649 }
650
651 /******************************************************************************
652 * SystemFunction041 (ADVAPI32.@)
653 *
654 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
655 *
656 * PARAMS
657 * memory [I/O] Pointer to memory to decrypt.
658 * length [I] Length of region to decrypt in bytes.
659 * flags [I] Control whether other processes are able to decrypt the memory.
660 * RTL_ENCRYPT_OPTION_SAME_PROCESS
661 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
662 * RTL_ENCRYPT_OPTION_SAME_LOGON
663 *
664 * RETURNS
665 * Success: STATUS_SUCCESS
666 * Failure: NTSTATUS error code
667 *
668 * NOTES
669 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
670 * If flags are specified when encrypting, the same flag value must be given
671 * when decrypting the memory.
672 */
673 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
674 {
675 //FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
676 return STATUS_SUCCESS;
677 }
678
679 /* EOF */