• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
permute(char * out,char * in,uchar * p,int n)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
lshift(char * d,int count,int n)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
concat(char * out,char * in1,char * in2,int l1,int l2)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
xor(char * out,char * in1,char * in2,int n)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
dohash(char * out,char * in,char * key,int forw)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
str_to_key(unsigned char * str,unsigned char * key)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 static void
smbhash(unsigned char * out,const unsigned char * in,unsigned char * key,int forw)321 smbhash(unsigned char *out, const unsigned char *in, unsigned char *key,
322 	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 	for (i = 0; i < 64; i++) {
351 		if (outb[i])
352 			out[i / 8] |= (1 << (7 - (i % 8)));
353 	}
354 	kfree(outb);
355 }
356 
357 void
E_P16(unsigned char * p14,unsigned char * p16)358 E_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 
366 void
E_P24(unsigned char * p21,const unsigned char * c8,unsigned char * p24)367 E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
368 {
369 	smbhash(p24, c8, p21, 1);
370 	smbhash(p24 + 8, c8, p21 + 7, 1);
371 	smbhash(p24 + 16, c8, p21 + 14, 1);
372 }
373 
374 #if 0 /* currently unsued */
375 static void
376 D_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 
382 static void
383 E_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 }
388 /* these routines are currently unneeded, but may be
389 	needed later */
390 void
391 cred_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 
399 void
400 cred_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 
410 void
411 cred_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 */
420