xref: /reactos/dll/win32/advapi32/wine/crypt_lmhash.c (revision 8da9b8d1)
1 /*
2  *  Copyright 2004 Hans Leidekker
3  *
4  *  Based on LMHash.c from libcifs
5  *
6  *  Copyright (C) 2004 by Christopher R. Hertel
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #ifdef __REACTOS__
24 #include <advapi32.h>
25 #else
26 #include <stdarg.h>
27 
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "windef.h"
31 #include "winternl.h"
32 
33 #include "crypt.h"
34 #endif
35 
36 static const unsigned char CRYPT_LMhash_Magic[8] =
37     { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
38 
CRYPT_LMhash(unsigned char * dst,const unsigned char * pwd,const int len)39 static void CRYPT_LMhash( unsigned char *dst, const unsigned char *pwd, const int len )
40 {
41     int i, max = 14;
42     unsigned char tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
43 
44     max = len > max ? max : len;
45 
46     for (i = 0; i < max; i++)
47         tmp_pwd[i] = pwd[i];
48 
49     CRYPT_DEShash( dst, tmp_pwd, CRYPT_LMhash_Magic );
50     CRYPT_DEShash( &dst[8], &tmp_pwd[7], CRYPT_LMhash_Magic );
51 }
52 
SystemFunction006(LPCSTR password,LPSTR hash)53 NTSTATUS WINAPI SystemFunction006( LPCSTR password, LPSTR hash )
54 {
55     CRYPT_LMhash( (unsigned char*)hash, (const unsigned char*)password, strlen(password) );
56 
57     return STATUS_SUCCESS;
58 }
59 
60 #ifndef __REACTOS__
61 /******************************************************************************
62  * SystemFunction008  [ADVAPI32.@]
63  *
64  * Creates a LM response from a challenge and a password hash
65  *
66  * PARAMS
67  *   challenge  [I] Challenge from authentication server
68  *   hash       [I] NTLM hash (from SystemFunction006)
69  *   response   [O] response to send back to the server
70  *
71  * RETURNS
72  *  Success: STATUS_SUCCESS
73  *  Failure: STATUS_UNSUCCESSFUL
74  *
75  * NOTES
76  *  see http://davenport.sourceforge.net/ntlm.html#theLmResponse
77  *
78  */
SystemFunction008(const BYTE * challenge,const BYTE * hash,LPBYTE response)79 NTSTATUS WINAPI SystemFunction008(const BYTE *challenge, const BYTE *hash, LPBYTE response)
80 {
81     BYTE key[7*3];
82 
83     if (!challenge || !response)
84         return STATUS_UNSUCCESSFUL;
85 
86     memset(key, 0, sizeof key);
87     memcpy(key, hash, 0x10);
88 
89     CRYPT_DEShash(response, key, challenge);
90     CRYPT_DEShash(response+8, key+7, challenge);
91     CRYPT_DEShash(response+16, key+14, challenge);
92 
93     return STATUS_SUCCESS;
94 }
95 
96 /******************************************************************************
97  * SystemFunction009  [ADVAPI32.@]
98  *
99  * Seems to do the same as SystemFunction008 ...
100  */
SystemFunction009(const BYTE * challenge,const BYTE * hash,LPBYTE response)101 NTSTATUS WINAPI SystemFunction009(const BYTE *challenge, const BYTE *hash, LPBYTE response)
102 {
103     return SystemFunction008(challenge, hash, response);
104 }
105 
106 /******************************************************************************
107  * SystemFunction001  [ADVAPI32.@]
108  *
109  * Encrypts a single block of data using DES
110  *
111  * PARAMS
112  *   data    [I] data to encrypt    (8 bytes)
113  *   key     [I] key data           (7 bytes)
114  *   output  [O] the encrypted data (8 bytes)
115  *
116  * RETURNS
117  *  Success: STATUS_SUCCESS
118  *  Failure: STATUS_UNSUCCESSFUL
119  *
120  */
SystemFunction001(const BYTE * data,const BYTE * key,LPBYTE output)121 NTSTATUS WINAPI SystemFunction001(const BYTE *data, const BYTE *key, LPBYTE output)
122 {
123     if (!data || !output)
124         return STATUS_UNSUCCESSFUL;
125     CRYPT_DEShash(output, key, data);
126     return STATUS_SUCCESS;
127 }
128 
129 /******************************************************************************
130  * SystemFunction002  [ADVAPI32.@]
131  *
132  * Decrypts a single block of data using DES
133  *
134  * PARAMS
135  *   data    [I] data to decrypt    (8 bytes)
136  *   key     [I] key data           (7 bytes)
137  *   output  [O] the decrypted data (8 bytes)
138  *
139  * RETURNS
140  *  Success: STATUS_SUCCESS
141  *  Failure: STATUS_UNSUCCESSFUL
142  *
143  */
SystemFunction002(const BYTE * data,const BYTE * key,LPBYTE output)144 NTSTATUS WINAPI SystemFunction002(const BYTE *data, const BYTE *key, LPBYTE output)
145 {
146     if (!data || !output)
147         return STATUS_UNSUCCESSFUL;
148     CRYPT_DESunhash(output, key, data);
149     return STATUS_SUCCESS;
150 }
151 
152 /******************************************************************************
153  * SystemFunction003  [ADVAPI32.@]
154  *
155  * Hashes a key using DES and a fixed datablock
156  *
157  * PARAMS
158  *   key     [I] key data    (7 bytes)
159  *   output  [O] hashed key  (8 bytes)
160  *
161  * RETURNS
162  *  Success: STATUS_SUCCESS
163  *  Failure: STATUS_UNSUCCESSFUL
164  *
165  */
SystemFunction003(const BYTE * key,LPBYTE output)166 NTSTATUS WINAPI SystemFunction003(const BYTE *key, LPBYTE output)
167 {
168     if (!output)
169         return STATUS_UNSUCCESSFUL;
170     CRYPT_DEShash(output, key, CRYPT_LMhash_Magic);
171     return STATUS_SUCCESS;
172 }
173 
174 /******************************************************************************
175  * SystemFunction004  [ADVAPI32.@]
176  *
177  * Encrypts a block of data with DES in ECB mode, preserving the length
178  *
179  * PARAMS
180  *   data    [I] data to encrypt
181  *   key     [I] key data (up to 7 bytes)
182  *   output  [O] buffer to receive encrypted data
183  *
184  * RETURNS
185  *  Success: STATUS_SUCCESS
186  *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
187  *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
188  *
189  * NOTES
190  *  Encrypt buffer size should be input size rounded up to 8 bytes
191  *   plus an extra 8 bytes.
192  */
SystemFunction004(const struct ustring * in,const struct ustring * key,struct ustring * out)193 NTSTATUS WINAPI SystemFunction004(const struct ustring *in,
194                                   const struct ustring *key,
195                                   struct ustring *out)
196 {
197     union {
198          unsigned char uc[8];
199          unsigned int  ui[2];
200     } data;
201     unsigned char deskey[7];
202     unsigned int crypt_len, ofs;
203 
204     if (key->Length<=0)
205         return STATUS_INVALID_PARAMETER_2;
206 
207     crypt_len = ((in->Length+7)&~7);
208     if (out->MaximumLength < (crypt_len+8))
209         return STATUS_BUFFER_TOO_SMALL;
210 
211     data.ui[0] = in->Length;
212     data.ui[1] = 1;
213 
214     if (key->Length<sizeof deskey)
215     {
216         memset(deskey, 0, sizeof deskey);
217         memcpy(deskey, key->Buffer, key->Length);
218     }
219     else
220         memcpy(deskey, key->Buffer, sizeof deskey);
221 
222     CRYPT_DEShash(out->Buffer, deskey, data.uc);
223 
224     for(ofs=0; ofs<(crypt_len-8); ofs+=8)
225         CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs);
226 
227     memset(data.uc, 0, sizeof data.uc);
228     memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len);
229     CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc);
230 
231     out->Length = crypt_len+8;
232 
233     return STATUS_SUCCESS;
234 }
235 
236 /******************************************************************************
237  * SystemFunction005  [ADVAPI32.@]
238  *
239  * Decrypts a block of data with DES in ECB mode
240  *
241  * PARAMS
242  *   data    [I] data to decrypt
243  *   key     [I] key data (up to 7 bytes)
244  *   output  [O] buffer to receive decrypted data
245  *
246  * RETURNS
247  *  Success: STATUS_SUCCESS
248  *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
249  *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
250  *
251  */
SystemFunction005(const struct ustring * in,const struct ustring * key,struct ustring * out)252 NTSTATUS WINAPI SystemFunction005(const struct ustring *in,
253                                   const struct ustring *key,
254                                   struct ustring *out)
255 {
256     union {
257          unsigned char uc[8];
258          unsigned int  ui[2];
259     } data;
260     unsigned char deskey[7];
261     unsigned int ofs, crypt_len;
262 
263     if (key->Length<=0)
264         return STATUS_INVALID_PARAMETER_2;
265 
266     if (key->Length<sizeof deskey)
267     {
268         memset(deskey, 0, sizeof deskey);
269         memcpy(deskey, key->Buffer, key->Length);
270     }
271     else
272         memcpy(deskey, key->Buffer, sizeof deskey);
273 
274     CRYPT_DESunhash(data.uc, deskey, in->Buffer);
275 
276     if (data.ui[1] != 1)
277         return STATUS_UNKNOWN_REVISION;
278 
279     crypt_len = data.ui[0];
280     if (crypt_len > out->MaximumLength)
281         return STATUS_BUFFER_TOO_SMALL;
282 
283     for (ofs=0; (ofs+8)<crypt_len; ofs+=8)
284         CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8);
285 
286     if (ofs<crypt_len)
287     {
288         CRYPT_DESunhash(data.uc, deskey, in->Buffer+ofs+8);
289         memcpy(out->Buffer+ofs, data.uc, crypt_len-ofs);
290     }
291 
292     out->Length = crypt_len;
293 
294     return STATUS_SUCCESS;
295 }
296 
297 /******************************************************************************
298  * SystemFunction012  [ADVAPI32.@]
299  * SystemFunction014  [ADVAPI32.@]
300  * SystemFunction016  [ADVAPI32.@]
301  * SystemFunction018  [ADVAPI32.@]
302  * SystemFunction020  [ADVAPI32.@]
303  * SystemFunction022  [ADVAPI32.@]
304  *
305  * Encrypts two DES blocks with two keys
306  *
307  * PARAMS
308  *   data    [I] data to encrypt (16 bytes)
309  *   key     [I] key data (two lots of 7 bytes)
310  *   output  [O] buffer to receive encrypted data (16 bytes)
311  *
312  * RETURNS
313  *  Success: STATUS_SUCCESS
314  *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
315  */
SystemFunction012(const BYTE * in,const BYTE * key,LPBYTE out)316 NTSTATUS WINAPI SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out)
317 {
318     if (!in || !out)
319         return STATUS_UNSUCCESSFUL;
320 
321     CRYPT_DEShash(out, key, in);
322     CRYPT_DEShash(out+8, key+7, in+8);
323     return STATUS_SUCCESS;
324 }
325 
326 /******************************************************************************
327  * SystemFunction013  [ADVAPI32.@]
328  * SystemFunction015  [ADVAPI32.@]
329  * SystemFunction017  [ADVAPI32.@]
330  * SystemFunction019  [ADVAPI32.@]
331  * SystemFunction021  [ADVAPI32.@]
332  * SystemFunction023  [ADVAPI32.@]
333  *
334  * Decrypts two DES blocks with two keys
335  *
336  * PARAMS
337  *   data    [I] data to decrypt (16 bytes)
338  *   key     [I] key data (two lots of 7 bytes)
339  *   output  [O] buffer to receive decrypted data (16 bytes)
340  *
341  * RETURNS
342  *  Success: STATUS_SUCCESS
343  *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
344  */
SystemFunction013(const BYTE * in,const BYTE * key,LPBYTE out)345 NTSTATUS WINAPI SystemFunction013(const BYTE *in, const BYTE *key, LPBYTE out)
346 {
347     if (!in || !out)
348         return STATUS_UNSUCCESSFUL;
349 
350     CRYPT_DESunhash(out, key, in);
351     CRYPT_DESunhash(out+8, key+7, in+8);
352     return STATUS_SUCCESS;
353 }
354 
355 /******************************************************************************
356  * SystemFunction024  [ADVAPI32.@]
357  *
358  * Encrypts two DES blocks with a 32 bit key...
359  *
360  * PARAMS
361  *   data    [I] data to encrypt (16 bytes)
362  *   key     [I] key data (4 bytes)
363  *   output  [O] buffer to receive encrypted data (16 bytes)
364  *
365  * RETURNS
366  *  Success: STATUS_SUCCESS
367  */
SystemFunction024(const BYTE * in,const BYTE * key,LPBYTE out)368 NTSTATUS WINAPI SystemFunction024(const BYTE *in, const BYTE *key, LPBYTE out)
369 {
370     BYTE deskey[0x10];
371 
372     memcpy(deskey, key, 4);
373     memcpy(deskey+4, key, 4);
374     memcpy(deskey+8, key, 4);
375     memcpy(deskey+12, key, 4);
376 
377     CRYPT_DEShash(out, deskey, in);
378     CRYPT_DEShash(out+8, deskey+7, in+8);
379 
380     return STATUS_SUCCESS;
381 }
382 
383 /******************************************************************************
384  * SystemFunction025  [ADVAPI32.@]
385  *
386  * Decrypts 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  */
SystemFunction025(const BYTE * in,const BYTE * key,LPBYTE out)396 NTSTATUS WINAPI SystemFunction025(const BYTE *in, const BYTE *key, LPBYTE out)
397 {
398     BYTE deskey[0x10];
399 
400     memcpy(deskey, key, 4);
401     memcpy(deskey+4, key, 4);
402     memcpy(deskey+8, key, 4);
403     memcpy(deskey+12, key, 4);
404 
405     CRYPT_DESunhash(out, deskey, in);
406     CRYPT_DESunhash(out+8, deskey+7, in+8);
407 
408     return STATUS_SUCCESS;
409 }
410 #endif /* !__REACTOS__ */
411