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