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