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 1997
9 Copyright 2006 The FreeRADIUS server project
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.
29 This code makes no attempt to be fast! In fact, it is a very
32 This code is NOT a complete DES implementation. It implements only
33 the minimum necessary for SMB authentication, as used by all SMB
34 products (including every copy of Microsoft Windows95 ever sold)
36 In particular, it can only do a unchained forward DES pass. This
37 means it is not possible to use this code for encryption/decryption
38 of data, instead it is only useful as a "hash" algorithm.
40 There is no entry point into this code that allows normal DES operation.
42 I believe this means that this code does not come under ITAR
43 regulations but this is NOT a legal opinion. If you are concerned
44 about the applicability of ITAR regulations to this code then you
45 should confirm it for yourself (and maybe let me know if you come
46 up with a different answer to the one above)
49 #include <freeradius-devel/ident.h>
54 static int perm1[56] = {57, 49, 41, 33, 25, 17, 9,
55 1, 58, 50, 42, 34, 26, 18,
56 10, 2, 59, 51, 43, 35, 27,
57 19, 11, 3, 60, 52, 44, 36,
58 63, 55, 47, 39, 31, 23, 15,
59 7, 62, 54, 46, 38, 30, 22,
60 14, 6, 61, 53, 45, 37, 29,
61 21, 13, 5, 28, 20, 12, 4};
63 static int perm2[48] = {14, 17, 11, 24, 1, 5,
67 41, 52, 31, 37, 47, 55,
68 30, 40, 51, 45, 33, 48,
69 44, 49, 39, 56, 34, 53,
70 46, 42, 50, 36, 29, 32};
72 static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
73 60, 52, 44, 36, 28, 20, 12, 4,
74 62, 54, 46, 38, 30, 22, 14, 6,
75 64, 56, 48, 40, 32, 24, 16, 8,
76 57, 49, 41, 33, 25, 17, 9, 1,
77 59, 51, 43, 35, 27, 19, 11, 3,
78 61, 53, 45, 37, 29, 21, 13, 5,
79 63, 55, 47, 39, 31, 23, 15, 7};
81 static int 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,
88 28, 29, 30, 31, 32, 1};
90 static int perm5[32] = { 16, 7, 20, 21,
100 static int perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
101 39, 7, 47, 15, 55, 23, 63, 31,
102 38, 6, 46, 14, 54, 22, 62, 30,
103 37, 5, 45, 13, 53, 21, 61, 29,
104 36, 4, 44, 12, 52, 20, 60, 28,
105 35, 3, 43, 11, 51, 19, 59, 27,
106 34, 2, 42, 10, 50, 18, 58, 26,
107 33, 1, 41, 9, 49, 17, 57, 25};
110 static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
112 static int sbox[8][4][16] = {
113 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
114 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
115 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
116 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
118 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
119 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
120 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
121 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
123 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
124 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
125 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
126 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
128 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
129 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
130 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
131 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
133 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
134 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
135 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
136 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
138 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
139 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
140 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
141 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
143 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
144 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
145 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
146 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
148 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
149 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
150 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
151 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
153 static void permute(char *out, char *in, int *p, int n)
160 static void lshift(char *d, int count, int n)
165 out[i] = d[(i+count)%n];
170 static void concat(char *out, char *in1, char *in2, int l1, int l2)
178 static void xor(char *out, char *in1, char *in2, int n)
182 out[i] = in1[i] ^ in2[i];
185 static void dohash(char *out, char *in, char *key)
197 permute(pk1, key, perm1, 56);
205 lshift(c, sc[i], 28);
206 lshift(d, sc[i], 28);
208 concat(cd, c, d, 28, 28);
209 permute(ki[i], cd, perm2, 48);
212 permute(pd1, in, perm3, 64);
227 permute(er, r, perm4, 48);
229 xor(erk, er, ki[i], 48);
233 b[j][k] = erk[j*6 + k];
237 m = (b[j][0]<<1) | b[j][5];
239 n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
242 b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
248 permute(pcb, cb, perm5, 32);
259 concat(rl, r, l, 32, 32);
261 permute(out, rl, perm6, 64);
264 static void str_to_key(unsigned char *str,unsigned char *key)
269 key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
270 key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
271 key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
272 key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
273 key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
274 key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
275 key[7] = str[6]&0x7F;
277 key[i] = (key[i]<<1);
282 static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
288 unsigned char key2[8];
290 str_to_key(key, key2);
293 inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
294 keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
298 dohash(outb, inb, keyb);
306 out[i/8] |= (1<<(7-(i%8)));
310 void E_P16(unsigned char *p14,unsigned char *p16)
312 unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
313 smbhash(p16, sp8, p14);
314 smbhash(p16+8, sp8, p14+7);
317 void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
319 smbhash(p24, c8, p21);
320 smbhash(p24+8, c8, p21+7);
321 smbhash(p24+16, c8, p21+14);
324 void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
326 unsigned char buf[8];
328 smbhash(buf, in, key);
329 smbhash(out, buf, key+9);
332 void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
334 unsigned char buf[8];
335 static unsigned char key2[8];
337 smbhash(buf, in, key);
339 smbhash(out, buf, key2);