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 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
118 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
120 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} },
121 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
123 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
124 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
125 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
126 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
127 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
129 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} },
130 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
132 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
133 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
134 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
135 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
136 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
138 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} },
139 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
141 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
142 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
143 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
144 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
145 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
147 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} },
148 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
150 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
151 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
152 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
153 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
154 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
156 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} },
157 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
159 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
160 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
161 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
162 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
163 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
165 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} },
166 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
168 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
169 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
170 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
171 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
172 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
174 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} },
175 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
177 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
178 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
179 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
180 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
181 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
183 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} }
184 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
188 permute(char *out
, char *in
, uchar
*p
, int n
)
191 for (i
= 0; i
< n
; i
++)
192 out
[i
] = in
[p
[i
] - 1];
196 lshift(char *d
, int count
, int n
)
200 for (i
= 0; i
< n
; i
++)
201 out
[i
] = d
[(i
+ count
) % n
];
202 for (i
= 0; i
< n
; i
++)
207 concat(char *out
, char *in1
, char *in2
, int l1
, int l2
)
216 xor(char *out
, char *in1
, char *in2
, int n
)
219 for (i
= 0; i
< n
; i
++)
220 out
[i
] = in1
[i
] ^ in2
[i
];
224 dohash(char *out
, char *in
, char *key
, int forw
)
236 /* Have to reduce stack usage */
237 pk1
= kmalloc(56+56+64+64, GFP_KERNEL
);
241 ki
= kmalloc(16*48, GFP_KERNEL
);
251 permute(pk1
, key
, perm1
, 56);
253 for (i
= 0; i
< 28; i
++)
255 for (i
= 0; i
< 28; i
++)
258 for (i
= 0; i
< 16; i
++) {
259 lshift(c
, sc
[i
], 28);
260 lshift(d
, sc
[i
], 28);
262 concat(cd
, c
, d
, 28, 28);
263 permute(ki
[i
], cd
, perm2
, 48);
266 permute(pd1
, in
, perm3
, 64);
268 for (j
= 0; j
< 32; j
++) {
273 for (i
= 0; i
< 16; i
++) {
274 char *er
; /* er[48] */
275 char *erk
; /* erk[48] */
277 char *cb
; /* cb[32] */
278 char *pcb
; /* pcb[32] */
279 char *r2
; /* r2[32] */
281 er
= kmalloc(48+48+32+32+32, GFP_KERNEL
);
292 permute(er
, r
, perm4
, 48);
294 xor(erk
, er
, ki
[forw
? i
: 15 - i
], 48);
296 for (j
= 0; j
< 8; j
++)
297 for (k
= 0; k
< 6; k
++)
298 b
[j
][k
] = erk
[j
* 6 + k
];
300 for (j
= 0; j
< 8; j
++) {
302 m
= (b
[j
][0] << 1) | b
[j
][5];
304 n
= (b
[j
][1] << 3) | (b
[j
][2] << 2) | (b
[j
][3] <<
307 for (k
= 0; k
< 4; k
++)
309 (sbox
[j
][m
][n
] & (1 << (3 - k
))) ? 1 : 0;
312 for (j
= 0; j
< 8; j
++)
313 for (k
= 0; k
< 4; k
++)
314 cb
[j
* 4 + k
] = b
[j
][k
];
315 permute(pcb
, cb
, perm5
, 32);
319 for (j
= 0; j
< 32; j
++)
322 for (j
= 0; j
< 32; j
++)
328 concat(rl
, r
, l
, 32, 32);
330 permute(out
, rl
, perm6
, 64);
336 str_to_key(unsigned char *str
, unsigned char *key
)
340 key
[0] = str
[0] >> 1;
341 key
[1] = ((str
[0] & 0x01) << 6) | (str
[1] >> 2);
342 key
[2] = ((str
[1] & 0x03) << 5) | (str
[2] >> 3);
343 key
[3] = ((str
[2] & 0x07) << 4) | (str
[3] >> 4);
344 key
[4] = ((str
[3] & 0x0F) << 3) | (str
[4] >> 5);
345 key
[5] = ((str
[4] & 0x1F) << 2) | (str
[5] >> 6);
346 key
[6] = ((str
[5] & 0x3F) << 1) | (str
[6] >> 7);
347 key
[7] = str
[6] & 0x7F;
348 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
349 for (i
= 0; i
< 8; i
++) {
351 for (i
= 0; i
< 8; i
++)
352 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
353 key
[i
] = (key
[i
] << 1);
354 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
357 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
361 smbhash(unsigned char *out
, unsigned char *in
, unsigned char *key
, int forw
)
364 char *outb
; /* outb[64] */
365 char *inb
; /* inb[64] */
366 char *keyb
; /* keyb[64] */
367 unsigned char key2
[8];
369 outb
= kmalloc(64 * 3, GFP_KERNEL
);
376 str_to_key(key
, key2
);
378 for (i
= 0; i
< 64; i
++) {
379 inb
[i
] = (in
[i
/ 8] & (1 << (7 - (i
% 8)))) ? 1 : 0;
380 keyb
[i
] = (key2
[i
/ 8] & (1 << (7 - (i
% 8)))) ? 1 : 0;
384 dohash(outb
, inb
, keyb
, forw
);
386 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
387 for (i
= 0; i
< 8; i
++) {
389 for (i
= 0; i
< 8; i
++)
390 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
392 <<<<<<< HEAD
:fs
/cifs
/smbdes
.c
395 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:fs
/cifs
/smbdes
.c
397 for (i
= 0; i
< 64; i
++) {
399 out
[i
/ 8] |= (1 << (7 - (i
% 8)));
405 E_P16(unsigned char *p14
, unsigned char *p16
)
407 unsigned char sp8
[8] =
408 { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
409 smbhash(p16
, sp8
, p14
, 1);
410 smbhash(p16
+ 8, sp8
, p14
+ 7, 1);
414 E_P24(unsigned char *p21
, unsigned char *c8
, unsigned char *p24
)
416 smbhash(p24
, c8
, p21
, 1);
417 smbhash(p24
+ 8, c8
, p21
+ 7, 1);
418 smbhash(p24
+ 16, c8
, p21
+ 14, 1);
421 #if 0 /* currently unsued */
423 D_P16(unsigned char *p14
, unsigned char *in
, unsigned char *out
)
425 smbhash(out
, in
, p14
, 0);
426 smbhash(out
+ 8, in
+ 8, p14
+ 7, 0);
430 E_old_pw_hash(unsigned char *p14
, unsigned char *in
, unsigned char *out
)
432 smbhash(out
, in
, p14
, 1);
433 smbhash(out
+ 8, in
+ 8, p14
+ 7, 1);
435 /* these routines are currently unneeded, but may be
438 cred_hash1(unsigned char *out
, unsigned char *in
, unsigned char *key
)
440 unsigned char buf
[8];
442 smbhash(buf
, in
, key
, 1);
443 smbhash(out
, buf
, key
+ 9, 1);
447 cred_hash2(unsigned char *out
, unsigned char *in
, unsigned char *key
)
449 unsigned char buf
[8];
450 static unsigned char key2
[8];
452 smbhash(buf
, in
, key
, 1);
454 smbhash(out
, buf
, key2
, 1);
458 cred_hash3(unsigned char *out
, unsigned char *in
, unsigned char *key
, int forw
)
460 static unsigned char key2
[8];
462 smbhash(out
, in
, key
, forw
);
464 smbhash(out
+ 8, in
+ 8, key2
, forw
);
466 #endif /* unneeded routines */