2 Unix SMB/Netbios implementation.
5 a partial implementation of DES designed for use in the
6 SMB authentication protocol
8 Copyright (C) Andrew Tridgell 1998
9 Modified by Steve French (sfrench@us.ibm.com) 2002,2004
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.
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.
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.
28 This code makes no attempt to be fast! In fact, it is a very
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)
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.
39 There is no entry point into this code that allows normal DES operation.
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)
47 #include <linux/slab.h>
48 #include "cifsencrypt.h"
49 #define uchar unsigned char
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
61 static uchar perm2
[48] = { 14, 17, 11, 24, 1, 5,
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
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
81 static uchar perm4
[48] = { 32, 1, 2, 3, 4, 5,
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,
91 static uchar perm5
[32] = { 16, 7, 20, 21,
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
111 static uchar sc
[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
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} },
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} },
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} },
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} },
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} },
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} },
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} },
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} }
156 permute(char *out
, char *in
, uchar
*p
, int n
)
159 for (i
= 0; i
< n
; i
++)
160 out
[i
] = in
[p
[i
] - 1];
164 lshift(char *d
, int count
, int n
)
168 for (i
= 0; i
< n
; i
++)
169 out
[i
] = d
[(i
+ count
) % n
];
170 for (i
= 0; i
< n
; i
++)
175 concat(char *out
, char *in1
, char *in2
, int l1
, int l2
)
184 xor(char *out
, char *in1
, char *in2
, int n
)
187 for (i
= 0; i
< n
; i
++)
188 out
[i
] = in1
[i
] ^ in2
[i
];
192 dohash(char *out
, char *in
, char *key
, int forw
)
204 /* Have to reduce stack usage */
205 pk1
= kmalloc(56+56+64+64, GFP_KERNEL
);
209 ki
= kmalloc(16*48, GFP_KERNEL
);
219 permute(pk1
, key
, perm1
, 56);
221 for (i
= 0; i
< 28; i
++)
223 for (i
= 0; i
< 28; i
++)
226 for (i
= 0; i
< 16; i
++) {
227 lshift(c
, sc
[i
], 28);
228 lshift(d
, sc
[i
], 28);
230 concat(cd
, c
, d
, 28, 28);
231 permute(ki
[i
], cd
, perm2
, 48);
234 permute(pd1
, in
, perm3
, 64);
236 for (j
= 0; j
< 32; j
++) {
241 for (i
= 0; i
< 16; i
++) {
242 char *er
; /* er[48] */
243 char *erk
; /* erk[48] */
245 char *cb
; /* cb[32] */
246 char *pcb
; /* pcb[32] */
247 char *r2
; /* r2[32] */
249 er
= kmalloc(48+48+32+32+32, GFP_KERNEL
);
260 permute(er
, r
, perm4
, 48);
262 xor(erk
, er
, ki
[forw
? i
: 15 - i
], 48);
264 for (j
= 0; j
< 8; j
++)
265 for (k
= 0; k
< 6; k
++)
266 b
[j
][k
] = erk
[j
* 6 + k
];
268 for (j
= 0; j
< 8; j
++) {
270 m
= (b
[j
][0] << 1) | b
[j
][5];
272 n
= (b
[j
][1] << 3) | (b
[j
][2] << 2) | (b
[j
][3] <<
275 for (k
= 0; k
< 4; k
++)
277 (sbox
[j
][m
][n
] & (1 << (3 - k
))) ? 1 : 0;
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);
287 for (j
= 0; j
< 32; j
++)
290 for (j
= 0; j
< 32; j
++)
296 concat(rl
, r
, l
, 32, 32);
298 permute(out
, rl
, perm6
, 64);
304 str_to_key(unsigned char *str
, unsigned char *key
)
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);
321 smbhash(unsigned char *out
, const unsigned char *in
, unsigned char *key
,
325 char *outb
; /* outb[64] */
326 char *inb
; /* inb[64] */
327 char *keyb
; /* keyb[64] */
328 unsigned char key2
[8];
330 outb
= kmalloc(64 * 3, GFP_KERNEL
);
337 str_to_key(key
, key2
);
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;
345 dohash(outb
, inb
, keyb
, forw
);
347 for (i
= 0; i
< 8; i
++)
350 for (i
= 0; i
< 64; i
++) {
352 out
[i
/ 8] |= (1 << (7 - (i
% 8)));
358 E_P16(unsigned char *p14
, unsigned char *p16
)
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);
367 E_P24(unsigned char *p21
, const unsigned char *c8
, unsigned char *p24
)
369 smbhash(p24
, c8
, p21
, 1);
370 smbhash(p24
+ 8, c8
, p21
+ 7, 1);
371 smbhash(p24
+ 16, c8
, p21
+ 14, 1);
374 #if 0 /* currently unused */
376 D_P16(unsigned char *p14
, unsigned char *in
, unsigned char *out
)
378 smbhash(out
, in
, p14
, 0);
379 smbhash(out
+ 8, in
+ 8, p14
+ 7, 0);
383 E_old_pw_hash(unsigned char *p14
, unsigned char *in
, unsigned char *out
)
385 smbhash(out
, in
, p14
, 1);
386 smbhash(out
+ 8, in
+ 8, p14
+ 7, 1);
388 /* these routines are currently unneeded, but may be
391 cred_hash1(unsigned char *out
, unsigned char *in
, unsigned char *key
)
393 unsigned char buf
[8];
395 smbhash(buf
, in
, key
, 1);
396 smbhash(out
, buf
, key
+ 9, 1);
400 cred_hash2(unsigned char *out
, unsigned char *in
, unsigned char *key
)
402 unsigned char buf
[8];
403 static unsigned char key2
[8];
405 smbhash(buf
, in
, key
, 1);
407 smbhash(out
, buf
, key2
, 1);
411 cred_hash3(unsigned char *out
, unsigned char *in
, unsigned char *key
, int forw
)
413 static unsigned char key2
[8];
415 smbhash(out
, in
, key
, forw
);
417 smbhash(out
+ 8, in
+ 8, key2
, forw
);
419 #endif /* unneeded routines */