blob: 224a1f4789666fe0e7873fa456ecc3915bb36cbd [file] [log] [blame]
Steve French38702532007-07-08 15:40:40 +00001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 Unix SMB/Netbios implementation.
3 Version 1.9.
4
Steve French38702532007-07-08 15:40:40 +00005 a partial implementation of DES designed for use in the
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 SMB authentication protocol
7
8 Copyright (C) Andrew Tridgell 1998
9 Modified by Steve French (sfrench@us.ibm.com) 2002,2004
Steve French50c2f752007-07-13 00:33:32 +000010
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 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.
Steve French50c2f752007-07-13 00:33:32 +000015
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 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.
Steve French50c2f752007-07-13 00:33:32 +000020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 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
Steve French38702532007-07-08 15:40:40 +000026/* NOTES:
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
28 This code makes no attempt to be fast! In fact, it is a very
Steve French38702532007-07-08 15:40:40 +000029 slow implementation
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
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
51static 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
61static 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
71static 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
81static 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
91static 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
101static 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
111static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
112
113static 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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000117 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000122 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000127 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000132 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000137 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000142 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000147 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
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},
Steve Frenchad7a2922008-02-07 23:25:02 +0000152 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153};
154
155static void
Steve French38702532007-07-08 15:40:40 +0000156permute(char *out, char *in, uchar *p, int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157{
158 int i;
159 for (i = 0; i < n; i++)
160 out[i] = in[p[i] - 1];
161}
162
163static void
164lshift(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
174static void
175concat(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
183static void
184xor(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
191static void
192dohash(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;
Steve French9a0c8232007-02-02 04:21:57 +0000199 char (*ki)[48];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 char *pd1;
201 char l[32], r[32];
202 char *rl;
203
204 /* Have to reduce stack usage */
Steve French38702532007-07-08 15:40:40 +0000205 pk1 = kmalloc(56+56+64+64, GFP_KERNEL);
206 if (pk1 == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 return;
208
Steve French9a0c8232007-02-02 04:21:57 +0000209 ki = kmalloc(16*48, GFP_KERNEL);
Steve French38702532007-07-08 15:40:40 +0000210 if (ki == NULL) {
Steve French914afcf2007-02-02 14:42:12 +0000211 kfree(pk1);
Steve French9a0c8232007-02-02 04:21:57 +0000212 return;
Steve French914afcf2007-02-02 14:42:12 +0000213 }
Steve French9a0c8232007-02-02 04:21:57 +0000214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 cd = pk1 + 56;
Steve French38702532007-07-08 15:40:40 +0000216 pd1 = cd + 56;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 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);
Steve French38702532007-07-08 15:40:40 +0000250 if (er == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 kfree(pk1);
Steve French9a0c8232007-02-02 04:21:57 +0000252 kfree(ki);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 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);
Steve French9a0c8232007-02-02 04:21:57 +0000300 kfree(ki);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301}
302
303static void
304str_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;
Steve Frenchad7a2922008-02-07 23:25:02 +0000316 for (i = 0; i < 8; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 key[i] = (key[i] << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318}
319
320static void
Jeff Layton4e53a3f2008-12-05 20:41:21 -0500321smbhash(unsigned char *out, const unsigned char *in, unsigned char *key,
322 int forw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
324 int i;
325 char *outb; /* outb[64] */
326 char *inb; /* inb[64] */
327 char *keyb; /* keyb[64] */
328 unsigned char key2[8];
329
Steve French38702532007-07-08 15:40:40 +0000330 outb = kmalloc(64 * 3, GFP_KERNEL);
331 if (outb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 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
Steve Frenchad7a2922008-02-07 23:25:02 +0000347 for (i = 0; i < 8; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 out[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 for (i = 0; i < 64; i++) {
351 if (outb[i])
352 out[i / 8] |= (1 << (7 - (i % 8)));
353 }
354 kfree(outb);
355}
356
357void
358E_P16(unsigned char *p14, unsigned char *p16)
359{
360 unsigned char sp8[8] =
361 { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
362 smbhash(p16, sp8, p14, 1);
363 smbhash(p16 + 8, sp8, p14 + 7, 1);
364}
365
366void
Jeff Layton4e53a3f2008-12-05 20:41:21 -0500367E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
369 smbhash(p24, c8, p21, 1);
370 smbhash(p24 + 8, c8, p21 + 7, 1);
371 smbhash(p24 + 16, c8, p21 + 14, 1);
372}
373
Steve Frenche10847e2006-09-28 20:49:01 +0000374#if 0 /* currently unsued */
Steve French2cd646a2006-09-28 19:43:08 +0000375static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
377{
378 smbhash(out, in, p14, 0);
379 smbhash(out + 8, in + 8, p14 + 7, 0);
380}
381
Steve French2cd646a2006-09-28 19:43:08 +0000382static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
384{
385 smbhash(out, in, p14, 1);
386 smbhash(out + 8, in + 8, p14 + 7, 1);
387}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388/* these routines are currently unneeded, but may be
389 needed later */
390void
391cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
392{
393 unsigned char buf[8];
394
395 smbhash(buf, in, key, 1);
396 smbhash(out, buf, key + 9, 1);
397}
398
399void
400cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
401{
402 unsigned char buf[8];
403 static unsigned char key2[8];
404
405 smbhash(buf, in, key, 1);
406 key2[0] = key[7];
407 smbhash(out, buf, key2, 1);
408}
409
410void
411cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
412{
413 static unsigned char key2[8];
414
415 smbhash(out, in, key, forw);
416 key2[0] = key[7];
417 smbhash(out + 8, in + 8, key2, forw);
418}
419#endif /* unneeded routines */