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