All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
smbdes.c
Go to the documentation of this file.
1 /*
2  Unix SMB/CIFS implementation.
3 
4  a partial implementation of DES designed for use in the
5  SMB authentication protocol
6 
7  Copyright (C) Andrew Tridgell 1998
8  Copyright 2006 The FreeRADIUS server project
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
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 
48 RCSID("$Id: 9fa5c86a16a070bc2a1700f252dd810c9f9e8f80 $")
49 
50 #include <string.h>
51 #include <ctype.h>
52 #include "eap_leap.h"
53 
54 #define uchar unsigned char
55 
56 static const uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9,
57  1, 58, 50, 42, 34, 26, 18,
58  10, 2, 59, 51, 43, 35, 27,
59  19, 11, 3, 60, 52, 44, 36,
60  63, 55, 47, 39, 31, 23, 15,
61  7, 62, 54, 46, 38, 30, 22,
62  14, 6, 61, 53, 45, 37, 29,
63  21, 13, 5, 28, 20, 12, 4};
64 
65 static const uchar perm2[48] = {14, 17, 11, 24, 1, 5,
66  3, 28, 15, 6, 21, 10,
67  23, 19, 12, 4, 26, 8,
68  16, 7, 27, 20, 13, 2,
69  41, 52, 31, 37, 47, 55,
70  30, 40, 51, 45, 33, 48,
71  44, 49, 39, 56, 34, 53,
72  46, 42, 50, 36, 29, 32};
73 
74 static const uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
75  60, 52, 44, 36, 28, 20, 12, 4,
76  62, 54, 46, 38, 30, 22, 14, 6,
77  64, 56, 48, 40, 32, 24, 16, 8,
78  57, 49, 41, 33, 25, 17, 9, 1,
79  59, 51, 43, 35, 27, 19, 11, 3,
80  61, 53, 45, 37, 29, 21, 13, 5,
81  63, 55, 47, 39, 31, 23, 15, 7};
82 
83 static const uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
84  4, 5, 6, 7, 8, 9,
85  8, 9, 10, 11, 12, 13,
86  12, 13, 14, 15, 16, 17,
87  16, 17, 18, 19, 20, 21,
88  20, 21, 22, 23, 24, 25,
89  24, 25, 26, 27, 28, 29,
90  28, 29, 30, 31, 32, 1};
91 
92 static const uchar perm5[32] = { 16, 7, 20, 21,
93  29, 12, 28, 17,
94  1, 15, 23, 26,
95  5, 18, 31, 10,
96  2, 8, 24, 14,
97  32, 27, 3, 9,
98  19, 13, 30, 6,
99  22, 11, 4, 25};
100 
101 
102 static const uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
103  39, 7, 47, 15, 55, 23, 63, 31,
104  38, 6, 46, 14, 54, 22, 62, 30,
105  37, 5, 45, 13, 53, 21, 61, 29,
106  36, 4, 44, 12, 52, 20, 60, 28,
107  35, 3, 43, 11, 51, 19, 59, 27,
108  34, 2, 42, 10, 50, 18, 58, 26,
109  33, 1, 41, 9, 49, 17, 57, 25};
110 
111 
112 static const uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
113 
114 static const uchar sbox[8][4][16] = {
115  {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
116  {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
117  {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
118  {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
119 
120  {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
121  {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
122  {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
123  {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
124 
125  {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
126  {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
127  {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
128  {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
129 
130  {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
131  {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
132  {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
133  {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
134 
135  {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
136  {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
137  {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
138  {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
139 
140  {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
141  {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
142  {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
143  {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
144 
145  {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
146  {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
147  {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
148  {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
149 
150  {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
151  {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
152  {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
153  {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
154 
155 static void permute(char *out, char const *in, uchar const *p, int n)
156 {
157  int i;
158  for (i=0;i<n;i++)
159  out[i] = in[p[i]-1];
160 }
161 
162 static void lshift(char *d, int count, int n)
163 {
164  char out[64];
165  int i;
166  for (i=0;i<n;i++)
167  out[i] = d[(i+count)%n];
168  for (i=0;i<n;i++)
169  d[i] = out[i];
170 }
171 
172 static void concat(char *out, char *in1, char *in2, int l1, int l2)
173 {
174  while (l1--)
175  *out++ = *in1++;
176  while (l2--)
177  *out++ = *in2++;
178 }
179 
180 static void xor(char *out, char *in1, char *in2, int n)
181 {
182  int i;
183  for (i=0;i<n;i++)
184  out[i] = in1[i] ^ in2[i];
185 }
186 
187 static void dohash(char *out, char *in, char *key)
188 {
189  int i, j, k;
190  char pk1[56];
191  char c[28];
192  char d[28];
193  char cd[56];
194  char ki[16][48];
195  char pd1[64];
196  char l[32], r[32];
197  char rl[64];
198 
199  permute(pk1, key, perm1, 56);
200 
201  for (i=0;i<28;i++)
202  c[i] = pk1[i];
203  for (i=0;i<28;i++)
204  d[i] = pk1[i+28];
205 
206  for (i=0;i<16;i++) {
207  lshift(c, sc[i], 28);
208  lshift(d, sc[i], 28);
209 
210  concat(cd, c, d, 28, 28);
211  permute(ki[i], cd, perm2, 48);
212  }
213 
214  permute(pd1, in, perm3, 64);
215 
216  for (j=0;j<32;j++) {
217  l[j] = pd1[j];
218  r[j] = pd1[j+32];
219  }
220 
221  for (i=0;i<16;i++) {
222  char er[48];
223  char erk[48];
224  char b[8][6];
225  char cb[32];
226  char pcb[32];
227  char r2[32];
228 
229  permute(er, r, perm4, 48);
230 
231  xor(erk, er, ki[i], 48);
232 
233  for (j=0;j<8;j++)
234  for (k=0;k<6;k++)
235  b[j][k] = erk[j*6 + k];
236 
237  for (j=0;j<8;j++) {
238  int m, n;
239  m = (b[j][0]<<1) | b[j][5];
240 
241  n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
242 
243  for (k=0;k<4;k++)
244  b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
245  }
246 
247  for (j=0;j<8;j++)
248  for (k=0;k<4;k++)
249  cb[j*4+k] = b[j][k];
250  permute(pcb, cb, perm5, 32);
251 
252  xor(r2, l, pcb, 32);
253 
254  for (j=0;j<32;j++)
255  l[j] = r[j];
256 
257  for (j=0;j<32;j++)
258  r[j] = r2[j];
259  }
260 
261  concat(rl, r, l, 32, 32);
262 
263  permute(out, rl, perm6, 64);
264 }
265 
266 static void str_to_key(unsigned char *str,unsigned char *key)
267 {
268  int i;
269 
270  key[0] = str[0]>>1;
271  key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
272  key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
273  key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
274  key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
275  key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
276  key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
277  key[7] = str[6]&0x7F;
278  for (i=0;i<8;i++) {
279  key[i] = (key[i]<<1);
280  }
281 }
282 
283 
284 static void smbhash(unsigned char *out, unsigned char const *in, unsigned char *key)
285 {
286  int i;
287  char outb[64];
288  char inb[64];
289  char keyb[64];
290  unsigned char key2[8];
291 
292  str_to_key(key, key2);
293 
294  for (i=0;i<64;i++) {
295  inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
296  keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
297  outb[i] = 0;
298  }
299 
300  dohash(outb, inb, keyb);
301 
302  for (i=0;i<8;i++) {
303  out[i] = 0;
304  }
305 
306  for (i=0;i<64;i++) {
307  if (outb[i])
308  out[i/8] |= (1<<(7-(i%8)));
309  }
310 }
311 
312 /*
313  * Take the NT or LM password, and return the MSCHAP response
314  *
315  * The win_password MUST be exactly 16 bytes long.
316  */
317 void eap_leap_mschap(unsigned char const *win_password, unsigned char const *challenge, unsigned char *response)
318 {
319  unsigned char p21[21];
320 
321  memset(p21, 0, sizeof(p21));
322  memcpy(p21, win_password, 16);
323 
324  smbhash(response, challenge, p21);
325  smbhash(response+8, challenge, p21+7);
326  smbhash(response+16, challenge, p21+14);
327 }
static void smbhash(unsigned char *out, unsigned char const *in, unsigned char *key)
Definition: smbdes.c:284
static void xor(char *out, char *in1, char *in2, int n)
Definition: smbdes.c:180
static void str_to_key(unsigned char *str, unsigned char *key)
Definition: smbdes.c:266
static void dohash(char *out, char *in, char *key)
Definition: smbdes.c:187
static const uchar perm5[32]
Definition: smbdes.c:92
#define uchar
Definition: smbdes.c:54
void eap_leap_mschap(unsigned char const *win_password, unsigned char const *challenge, unsigned char *response)
Definition: smbdes.c:317
static const uchar perm1[56]
Definition: smbdes.c:56
static const uchar perm6[64]
Definition: smbdes.c:102
static void permute(char *out, char const *in, uchar const *p, int n)
Definition: smbdes.c:155
static const uchar perm3[64]
Definition: smbdes.c:74
static const uchar perm2[48]
Definition: smbdes.c:65
static const uchar perm4[48]
Definition: smbdes.c:83
static const uchar sbox[8][4][16]
Definition: smbdes.c:114
static void concat(char *out, char *in1, char *in2, int l1, int l2)
Definition: smbdes.c:172
#define RCSID(id)
Definition: build.h:135
static int r
Definition: rbmonkey.c:66
static const uchar sc[16]
Definition: smbdes.c:112
static void lshift(char *d, int count, int n)
Definition: smbdes.c:162