ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / fs / cifs / smbdes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4
5    a partial implementation of DES designed for use in the 
6    SMB authentication protocol
7
8    Copyright (C) Andrew Tridgell 1998
9    Modified by Steve French (sfrench@us.ibm.com) 2002,2004
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /* NOTES: 
27
28    This code makes no attempt to be fast! In fact, it is a very
29    slow implementation 
30
31    This code is NOT a complete DES implementation. It implements only
32    the minimum necessary for SMB authentication, as used by all SMB
33    products (including every copy of Microsoft Windows95 ever sold)
34
35    In particular, it can only do a unchained forward DES pass. This
36    means it is not possible to use this code for encryption/decryption
37    of data, instead it is only useful as a "hash" algorithm.
38
39    There is no entry point into this code that allows normal DES operation.
40
41    I believe this means that this code does not come under ITAR
42    regulations but this is NOT a legal opinion. If you are concerned
43    about the applicability of ITAR regulations to this code then you
44    should confirm it for yourself (and maybe let me know if you come
45    up with a different answer to the one above)
46 */
47 #include <linux/slab.h>
48 #define uchar unsigned char
49
50 static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
51         1, 58, 50, 42, 34, 26, 18,
52         10, 2, 59, 51, 43, 35, 27,
53         19, 11, 3, 60, 52, 44, 36,
54         63, 55, 47, 39, 31, 23, 15,
55         7, 62, 54, 46, 38, 30, 22,
56         14, 6, 61, 53, 45, 37, 29,
57         21, 13, 5, 28, 20, 12, 4
58 };
59
60 static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
61         3, 28, 15, 6, 21, 10,
62         23, 19, 12, 4, 26, 8,
63         16, 7, 27, 20, 13, 2,
64         41, 52, 31, 37, 47, 55,
65         30, 40, 51, 45, 33, 48,
66         44, 49, 39, 56, 34, 53,
67         46, 42, 50, 36, 29, 32
68 };
69
70 static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
71         60, 52, 44, 36, 28, 20, 12, 4,
72         62, 54, 46, 38, 30, 22, 14, 6,
73         64, 56, 48, 40, 32, 24, 16, 8,
74         57, 49, 41, 33, 25, 17, 9, 1,
75         59, 51, 43, 35, 27, 19, 11, 3,
76         61, 53, 45, 37, 29, 21, 13, 5,
77         63, 55, 47, 39, 31, 23, 15, 7
78 };
79
80 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
81         4, 5, 6, 7, 8, 9,
82         8, 9, 10, 11, 12, 13,
83         12, 13, 14, 15, 16, 17,
84         16, 17, 18, 19, 20, 21,
85         20, 21, 22, 23, 24, 25,
86         24, 25, 26, 27, 28, 29,
87         28, 29, 30, 31, 32, 1
88 };
89
90 static uchar perm5[32] = { 16, 7, 20, 21,
91         29, 12, 28, 17,
92         1, 15, 23, 26,
93         5, 18, 31, 10,
94         2, 8, 24, 14,
95         32, 27, 3, 9,
96         19, 13, 30, 6,
97         22, 11, 4, 25
98 };
99
100 static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
101         39, 7, 47, 15, 55, 23, 63, 31,
102         38, 6, 46, 14, 54, 22, 62, 30,
103         37, 5, 45, 13, 53, 21, 61, 29,
104         36, 4, 44, 12, 52, 20, 60, 28,
105         35, 3, 43, 11, 51, 19, 59, 27,
106         34, 2, 42, 10, 50, 18, 58, 26,
107         33, 1, 41, 9, 49, 17, 57, 25
108 };
109
110 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
111
112 static uchar sbox[8][4][16] = {
113         {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
114          {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
115          {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
116          {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
117
118         {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
119          {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
120          {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
121          {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
122
123         {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
124          {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
125          {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
126          {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
127
128         {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
129          {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
130          {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
131          {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
132
133         {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
134          {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
135          {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
136          {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
137
138         {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
139          {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
140          {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
141          {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
142
143         {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
144          {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
145          {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
146          {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
147
148         {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
149          {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
150          {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
151          {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
152 };
153
154 static void
155 permute(char *out, char *in, uchar * p, int n)
156 {
157         int i;
158         for (i = 0; i < n; i++)
159                 out[i] = in[p[i] - 1];
160 }
161
162 static void
163 lshift(char *d, int count, int n)
164 {
165         char out[64];
166         int i;
167         for (i = 0; i < n; i++)
168                 out[i] = d[(i + count) % n];
169         for (i = 0; i < n; i++)
170                 d[i] = out[i];
171 }
172
173 static void
174 concat(char *out, char *in1, char *in2, int l1, int l2)
175 {
176         while (l1--)
177                 *out++ = *in1++;
178         while (l2--)
179                 *out++ = *in2++;
180 }
181
182 static void
183 xor(char *out, char *in1, char *in2, int n)
184 {
185         int i;
186         for (i = 0; i < n; i++)
187                 out[i] = in1[i] ^ in2[i];
188 }
189
190 static void
191 dohash(char *out, char *in, char *key, int forw)
192 {
193         int i, j, k;
194         char *pk1;
195         char c[28];
196         char d[28];
197         char *cd;
198         char ki[16][48];
199         char *pd1;
200         char l[32], r[32];
201         char *rl;
202
203         /* Have to reduce stack usage */
204         pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
205         if(pk1 == NULL)
206                 return;
207
208         cd = pk1 + 56;
209         pd1= cd  + 56;
210         rl = pd1 + 64;
211
212         permute(pk1, key, perm1, 56);
213
214         for (i = 0; i < 28; i++)
215                 c[i] = pk1[i];
216         for (i = 0; i < 28; i++)
217                 d[i] = pk1[i + 28];
218
219         for (i = 0; i < 16; i++) {
220                 lshift(c, sc[i], 28);
221                 lshift(d, sc[i], 28);
222
223                 concat(cd, c, d, 28, 28);
224                 permute(ki[i], cd, perm2, 48);
225         }
226
227         permute(pd1, in, perm3, 64);
228
229         for (j = 0; j < 32; j++) {
230                 l[j] = pd1[j];
231                 r[j] = pd1[j + 32];
232         }
233
234         for (i = 0; i < 16; i++) {
235                 char *er;  /* er[48]  */
236                 char *erk; /* erk[48] */
237                 char b[8][6];
238                 char *cb;  /* cb[32]  */
239                 char *pcb; /* pcb[32] */
240                 char *r2;  /* r2[32]  */
241
242                 er = kmalloc(48+48+32+32+32, GFP_KERNEL);
243                 if(er == NULL) {
244                         kfree(pk1);
245                         return;
246                 }
247                 erk = er+48;
248                 cb  = erk+48;
249                 pcb = cb+32;
250                 r2  = pcb+32;
251
252                 permute(er, r, perm4, 48);
253
254                 xor(erk, er, ki[forw ? i : 15 - i], 48);
255
256                 for (j = 0; j < 8; j++)
257                         for (k = 0; k < 6; k++)
258                                 b[j][k] = erk[j * 6 + k];
259
260                 for (j = 0; j < 8; j++) {
261                         int m, n;
262                         m = (b[j][0] << 1) | b[j][5];
263
264                         n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
265                                                                1) | b[j][4];
266
267                         for (k = 0; k < 4; k++)
268                                 b[j][k] =
269                                     (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
270                 }
271
272                 for (j = 0; j < 8; j++)
273                         for (k = 0; k < 4; k++)
274                                 cb[j * 4 + k] = b[j][k];
275                 permute(pcb, cb, perm5, 32);
276
277                 xor(r2, l, pcb, 32);
278
279                 for (j = 0; j < 32; j++)
280                         l[j] = r[j];
281
282                 for (j = 0; j < 32; j++)
283                         r[j] = r2[j];
284
285                 kfree(er);
286         }
287
288         concat(rl, r, l, 32, 32);
289
290         permute(out, rl, perm6, 64);
291         kfree(pk1);
292 }
293
294 static void
295 str_to_key(unsigned char *str, unsigned char *key)
296 {
297         int i;
298
299         key[0] = str[0] >> 1;
300         key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
301         key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
302         key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
303         key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
304         key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
305         key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
306         key[7] = str[6] & 0x7F;
307         for (i = 0; i < 8; i++) {
308                 key[i] = (key[i] << 1);
309         }
310 }
311
312 static void
313 smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
314 {
315         int i;
316         char *outb; /* outb[64] */
317         char *inb;  /* inb[64]  */
318         char *keyb; /* keyb[64] */
319         unsigned char key2[8];
320
321         outb = kmalloc(64 * 3,GFP_KERNEL);
322         if(outb == NULL)
323                 return;
324
325         inb  = outb + 64;
326         keyb = inb +  64;
327
328         str_to_key(key, key2);
329
330         for (i = 0; i < 64; i++) {
331                 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
332                 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
333                 outb[i] = 0;
334         }
335
336         dohash(outb, inb, keyb, forw);
337
338         for (i = 0; i < 8; i++) {
339                 out[i] = 0;
340         }
341
342         for (i = 0; i < 64; i++) {
343                 if (outb[i])
344                         out[i / 8] |= (1 << (7 - (i % 8)));
345         }
346         kfree(outb);
347 }
348
349 void
350 E_P16(unsigned char *p14, unsigned char *p16)
351 {
352         unsigned char sp8[8] =
353             { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
354         smbhash(p16, sp8, p14, 1);
355         smbhash(p16 + 8, sp8, p14 + 7, 1);
356 }
357
358 void
359 E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
360 {
361         smbhash(p24, c8, p21, 1);
362         smbhash(p24 + 8, c8, p21 + 7, 1);
363         smbhash(p24 + 16, c8, p21 + 14, 1);
364 }
365
366 void
367 D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
368 {
369         smbhash(out, in, p14, 0);
370         smbhash(out + 8, in + 8, p14 + 7, 0);
371 }
372
373 void
374 E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
375 {
376         smbhash(out, in, p14, 1);
377         smbhash(out + 8, in + 8, p14 + 7, 1);
378 }
379
380 void
381 cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
382 {
383         unsigned char buf[8];
384
385         smbhash(buf, in, key, 1);
386         smbhash(out, buf, key + 9, 1);
387 }
388
389 void
390 cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
391 {
392         unsigned char buf[8];
393         static unsigned char key2[8];
394
395         smbhash(buf, in, key, 1);
396         key2[0] = key[7];
397         smbhash(out, buf, key2, 1);
398 }
399
400 void
401 cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
402 {
403         static unsigned char key2[8];
404
405         smbhash(out, in, key, forw);
406         key2[0] = key[7];
407         smbhash(out + 8, in + 8, key2, forw);
408 }