block: fix blkdev_issue_flush() not detecting and passing EOPNOTSUPP back
[sfrench/cifs-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 #include "cifsencrypt.h"
49 #define uchar unsigned char
50
51 static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
52         1, 58, 50, 42, 34, 26, 18,
53         10, 2, 59, 51, 43, 35, 27,
54         19, 11, 3, 60, 52, 44, 36,
55         63, 55, 47, 39, 31, 23, 15,
56         7, 62, 54, 46, 38, 30, 22,
57         14, 6, 61, 53, 45, 37, 29,
58         21, 13, 5, 28, 20, 12, 4
59 };
60
61 static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
62         3, 28, 15, 6, 21, 10,
63         23, 19, 12, 4, 26, 8,
64         16, 7, 27, 20, 13, 2,
65         41, 52, 31, 37, 47, 55,
66         30, 40, 51, 45, 33, 48,
67         44, 49, 39, 56, 34, 53,
68         46, 42, 50, 36, 29, 32
69 };
70
71 static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
72         60, 52, 44, 36, 28, 20, 12, 4,
73         62, 54, 46, 38, 30, 22, 14, 6,
74         64, 56, 48, 40, 32, 24, 16, 8,
75         57, 49, 41, 33, 25, 17, 9, 1,
76         59, 51, 43, 35, 27, 19, 11, 3,
77         61, 53, 45, 37, 29, 21, 13, 5,
78         63, 55, 47, 39, 31, 23, 15, 7
79 };
80
81 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
82         4, 5, 6, 7, 8, 9,
83         8, 9, 10, 11, 12, 13,
84         12, 13, 14, 15, 16, 17,
85         16, 17, 18, 19, 20, 21,
86         20, 21, 22, 23, 24, 25,
87         24, 25, 26, 27, 28, 29,
88         28, 29, 30, 31, 32, 1
89 };
90
91 static uchar perm5[32] = { 16, 7, 20, 21,
92         29, 12, 28, 17,
93         1, 15, 23, 26,
94         5, 18, 31, 10,
95         2, 8, 24, 14,
96         32, 27, 3, 9,
97         19, 13, 30, 6,
98         22, 11, 4, 25
99 };
100
101 static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
102         39, 7, 47, 15, 55, 23, 63, 31,
103         38, 6, 46, 14, 54, 22, 62, 30,
104         37, 5, 45, 13, 53, 21, 61, 29,
105         36, 4, 44, 12, 52, 20, 60, 28,
106         35, 3, 43, 11, 51, 19, 59, 27,
107         34, 2, 42, 10, 50, 18, 58, 26,
108         33, 1, 41, 9, 49, 17, 57, 25
109 };
110
111 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
112
113 static uchar sbox[8][4][16] = {
114         {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
115          {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
116          {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
117          {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
118
119         {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
120          {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
121          {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
122          {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
123
124         {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
125          {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
126          {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
127          {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
128
129         {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
130          {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
131          {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
132          {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
133
134         {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
135          {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
136          {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
137          {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
138
139         {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
140          {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
141          {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
142          {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
143
144         {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
145          {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
146          {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
147          {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
148
149         {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
150          {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
151          {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
152          {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
153 };
154
155 static void
156 permute(char *out, char *in, uchar *p, int n)
157 {
158         int i;
159         for (i = 0; i < n; i++)
160                 out[i] = in[p[i] - 1];
161 }
162
163 static void
164 lshift(char *d, int count, int n)
165 {
166         char out[64];
167         int i;
168         for (i = 0; i < n; i++)
169                 out[i] = d[(i + count) % n];
170         for (i = 0; i < n; i++)
171                 d[i] = out[i];
172 }
173
174 static void
175 concat(char *out, char *in1, char *in2, int l1, int l2)
176 {
177         while (l1--)
178                 *out++ = *in1++;
179         while (l2--)
180                 *out++ = *in2++;
181 }
182
183 static void
184 xor(char *out, char *in1, char *in2, int n)
185 {
186         int i;
187         for (i = 0; i < n; i++)
188                 out[i] = in1[i] ^ in2[i];
189 }
190
191 static void
192 dohash(char *out, char *in, char *key, int forw)
193 {
194         int i, j, k;
195         char *pk1;
196         char c[28];
197         char d[28];
198         char *cd;
199         char (*ki)[48];
200         char *pd1;
201         char l[32], r[32];
202         char *rl;
203
204         /* Have to reduce stack usage */
205         pk1 = kmalloc(56+56+64+64, GFP_KERNEL);
206         if (pk1 == NULL)
207                 return;
208
209         ki = kmalloc(16*48, GFP_KERNEL);
210         if (ki == NULL) {
211                 kfree(pk1);
212                 return;
213         }
214
215         cd = pk1 + 56;
216         pd1 = cd  + 56;
217         rl = pd1 + 64;
218
219         permute(pk1, key, perm1, 56);
220
221         for (i = 0; i < 28; i++)
222                 c[i] = pk1[i];
223         for (i = 0; i < 28; i++)
224                 d[i] = pk1[i + 28];
225
226         for (i = 0; i < 16; i++) {
227                 lshift(c, sc[i], 28);
228                 lshift(d, sc[i], 28);
229
230                 concat(cd, c, d, 28, 28);
231                 permute(ki[i], cd, perm2, 48);
232         }
233
234         permute(pd1, in, perm3, 64);
235
236         for (j = 0; j < 32; j++) {
237                 l[j] = pd1[j];
238                 r[j] = pd1[j + 32];
239         }
240
241         for (i = 0; i < 16; i++) {
242                 char *er;  /* er[48]  */
243                 char *erk; /* erk[48] */
244                 char b[8][6];
245                 char *cb;  /* cb[32]  */
246                 char *pcb; /* pcb[32] */
247                 char *r2;  /* r2[32]  */
248
249                 er = kmalloc(48+48+32+32+32, GFP_KERNEL);
250                 if (er == NULL) {
251                         kfree(pk1);
252                         kfree(ki);
253                         return;
254                 }
255                 erk = er+48;
256                 cb  = erk+48;
257                 pcb = cb+32;
258                 r2  = pcb+32;
259
260                 permute(er, r, perm4, 48);
261
262                 xor(erk, er, ki[forw ? i : 15 - i], 48);
263
264                 for (j = 0; j < 8; j++)
265                         for (k = 0; k < 6; k++)
266                                 b[j][k] = erk[j * 6 + k];
267
268                 for (j = 0; j < 8; j++) {
269                         int m, n;
270                         m = (b[j][0] << 1) | b[j][5];
271
272                         n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
273                                                                1) | b[j][4];
274
275                         for (k = 0; k < 4; k++)
276                                 b[j][k] =
277                                     (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
278                 }
279
280                 for (j = 0; j < 8; j++)
281                         for (k = 0; k < 4; k++)
282                                 cb[j * 4 + k] = b[j][k];
283                 permute(pcb, cb, perm5, 32);
284
285                 xor(r2, l, pcb, 32);
286
287                 for (j = 0; j < 32; j++)
288                         l[j] = r[j];
289
290                 for (j = 0; j < 32; j++)
291                         r[j] = r2[j];
292
293                 kfree(er);
294         }
295
296         concat(rl, r, l, 32, 32);
297
298         permute(out, rl, perm6, 64);
299         kfree(pk1);
300         kfree(ki);
301 }
302
303 static void
304 str_to_key(unsigned char *str, unsigned char *key)
305 {
306         int i;
307
308         key[0] = str[0] >> 1;
309         key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
310         key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
311         key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
312         key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
313         key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
314         key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
315         key[7] = str[6] & 0x7F;
316         for (i = 0; i < 8; i++) {
317                 key[i] = (key[i] << 1);
318         }
319 }
320
321 static void
322 smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
323 {
324         int i;
325         char *outb; /* outb[64] */
326         char *inb;  /* inb[64]  */
327         char *keyb; /* keyb[64] */
328         unsigned char key2[8];
329
330         outb = kmalloc(64 * 3, GFP_KERNEL);
331         if (outb == NULL)
332                 return;
333
334         inb  = outb + 64;
335         keyb = inb +  64;
336
337         str_to_key(key, key2);
338
339         for (i = 0; i < 64; i++) {
340                 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
341                 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
342                 outb[i] = 0;
343         }
344
345         dohash(outb, inb, keyb, forw);
346
347         for (i = 0; i < 8; i++) {
348                 out[i] = 0;
349         }
350
351         for (i = 0; i < 64; i++) {
352                 if (outb[i])
353                         out[i / 8] |= (1 << (7 - (i % 8)));
354         }
355         kfree(outb);
356 }
357
358 void
359 E_P16(unsigned char *p14, unsigned char *p16)
360 {
361         unsigned char sp8[8] =
362             { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
363         smbhash(p16, sp8, p14, 1);
364         smbhash(p16 + 8, sp8, p14 + 7, 1);
365 }
366
367 void
368 E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
369 {
370         smbhash(p24, c8, p21, 1);
371         smbhash(p24 + 8, c8, p21 + 7, 1);
372         smbhash(p24 + 16, c8, p21 + 14, 1);
373 }
374
375 #if 0 /* currently unsued */
376 static void
377 D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
378 {
379         smbhash(out, in, p14, 0);
380         smbhash(out + 8, in + 8, p14 + 7, 0);
381 }
382
383 static void
384 E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
385 {
386         smbhash(out, in, p14, 1);
387         smbhash(out + 8, in + 8, p14 + 7, 1);
388 }
389 /* these routines are currently unneeded, but may be
390         needed later */
391 void
392 cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
393 {
394         unsigned char buf[8];
395
396         smbhash(buf, in, key, 1);
397         smbhash(out, buf, key + 9, 1);
398 }
399
400 void
401 cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
402 {
403         unsigned char buf[8];
404         static unsigned char key2[8];
405
406         smbhash(buf, in, key, 1);
407         key2[0] = key[7];
408         smbhash(out, buf, key2, 1);
409 }
410
411 void
412 cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
413 {
414         static unsigned char key2[8];
415
416         smbhash(out, in, key, forw);
417         key2[0] = key[7];
418         smbhash(out + 8, in + 8, key2, forw);
419 }
420 #endif /* unneeded routines */