compile with optimisation by default on all compilers
[Samba/gbeck.git] / source / libsmb / smbdes.c
blobd0e1c6e85fb00d0c91c0af57f5f1d74dc018f04e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
5 a partial implementation of DES designed for use in the
6 SMB authentication protocol
8 Copyright (C) Andrew Tridgell 1998
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.
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.
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.
25 #include "includes.h"
27 /* NOTES:
29 This code makes no attempt to be fast! In fact, it is a very
30 slow implementation
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)
50 #define uchar unsigned char
52 static uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9,
53 1, 58, 50, 42, 34, 26, 18,
54 10, 2, 59, 51, 43, 35, 27,
55 19, 11, 3, 60, 52, 44, 36,
56 63, 55, 47, 39, 31, 23, 15,
57 7, 62, 54, 46, 38, 30, 22,
58 14, 6, 61, 53, 45, 37, 29,
59 21, 13, 5, 28, 20, 12, 4};
61 static uchar perm2[48] = {14, 17, 11, 24, 1, 5,
62 3, 28, 15, 6, 21, 10,
63 23, 19, 12, 4, 26, 8,
64 16, 7, 27, 20, 13, 2,
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};
70 static uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
71 60, 52, 44, 36, 28, 20, 12, 4,
72 62, 54, 46, 38, 30, 22, 14, 6,
73 64, 56, 48, 40, 32, 24, 16, 8,
74 57, 49, 41, 33, 25, 17, 9, 1,
75 59, 51, 43, 35, 27, 19, 11, 3,
76 61, 53, 45, 37, 29, 21, 13, 5,
77 63, 55, 47, 39, 31, 23, 15, 7};
79 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
80 4, 5, 6, 7, 8, 9,
81 8, 9, 10, 11, 12, 13,
82 12, 13, 14, 15, 16, 17,
83 16, 17, 18, 19, 20, 21,
84 20, 21, 22, 23, 24, 25,
85 24, 25, 26, 27, 28, 29,
86 28, 29, 30, 31, 32, 1};
88 static uchar perm5[32] = { 16, 7, 20, 21,
89 29, 12, 28, 17,
90 1, 15, 23, 26,
91 5, 18, 31, 10,
92 2, 8, 24, 14,
93 32, 27, 3, 9,
94 19, 13, 30, 6,
95 22, 11, 4, 25};
98 static uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
99 39, 7, 47, 15, 55, 23, 63, 31,
100 38, 6, 46, 14, 54, 22, 62, 30,
101 37, 5, 45, 13, 53, 21, 61, 29,
102 36, 4, 44, 12, 52, 20, 60, 28,
103 35, 3, 43, 11, 51, 19, 59, 27,
104 34, 2, 42, 10, 50, 18, 58, 26,
105 33, 1, 41, 9, 49, 17, 57, 25};
108 static uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
110 static uchar sbox[8][4][16] = {
111 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
112 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
113 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
114 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
116 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
117 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
118 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
119 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
121 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
122 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
123 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
124 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
126 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
127 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
128 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
129 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
131 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
132 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
133 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
134 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
136 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
137 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
138 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
139 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
141 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
142 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
143 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
144 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
146 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
147 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
148 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
149 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
151 static void permute(char *out, char *in, uchar *p, int n)
153 int i;
154 for (i=0;i<n;i++)
155 out[i] = in[p[i]-1];
158 static void lshift(char *d, int count, int n)
160 char out[64];
161 int i;
162 for (i=0;i<n;i++)
163 out[i] = d[(i+count)%n];
164 for (i=0;i<n;i++)
165 d[i] = out[i];
168 static void concat(char *out, char *in1, char *in2, int l1, int l2)
170 while (l1--)
171 *out++ = *in1++;
172 while (l2--)
173 *out++ = *in2++;
176 static void xor(char *out, char *in1, char *in2, int n)
178 int i;
179 for (i=0;i<n;i++)
180 out[i] = in1[i] ^ in2[i];
183 static void dohash(char *out, char *in, char *key, int forw)
185 int i, j, k;
186 char pk1[56];
187 char c[28];
188 char d[28];
189 char cd[56];
190 char ki[16][48];
191 char pd1[64];
192 char l[32], r[32];
193 char rl[64];
195 permute(pk1, key, perm1, 56);
197 for (i=0;i<28;i++)
198 c[i] = pk1[i];
199 for (i=0;i<28;i++)
200 d[i] = pk1[i+28];
202 for (i=0;i<16;i++) {
203 lshift(c, sc[i], 28);
204 lshift(d, sc[i], 28);
206 concat(cd, c, d, 28, 28);
207 permute(ki[i], cd, perm2, 48);
210 permute(pd1, in, perm3, 64);
212 for (j=0;j<32;j++) {
213 l[j] = pd1[j];
214 r[j] = pd1[j+32];
217 for (i=0;i<16;i++) {
218 char er[48];
219 char erk[48];
220 char b[8][6];
221 char cb[32];
222 char pcb[32];
223 char r2[32];
225 permute(er, r, perm4, 48);
227 xor(erk, er, ki[forw ? i : 15 - i], 48);
229 for (j=0;j<8;j++)
230 for (k=0;k<6;k++)
231 b[j][k] = erk[j*6 + k];
233 for (j=0;j<8;j++) {
234 int m, n;
235 m = (b[j][0]<<1) | b[j][5];
237 n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
239 for (k=0;k<4;k++)
240 b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
243 for (j=0;j<8;j++)
244 for (k=0;k<4;k++)
245 cb[j*4+k] = b[j][k];
246 permute(pcb, cb, perm5, 32);
248 xor(r2, l, pcb, 32);
250 for (j=0;j<32;j++)
251 l[j] = r[j];
253 for (j=0;j<32;j++)
254 r[j] = r2[j];
257 concat(rl, r, l, 32, 32);
259 permute(out, rl, perm6, 64);
262 static void str_to_key(unsigned char *str,unsigned char *key)
264 int i;
266 key[0] = str[0]>>1;
267 key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
268 key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
269 key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
270 key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
271 key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
272 key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
273 key[7] = str[6]&0x7F;
274 for (i=0;i<8;i++) {
275 key[i] = (key[i]<<1);
280 static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
282 int i;
283 char outb[64];
284 char inb[64];
285 char keyb[64];
286 unsigned char key2[8];
288 str_to_key(key, key2);
290 for (i=0;i<64;i++) {
291 inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
292 keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
293 outb[i] = 0;
296 dohash(outb, inb, keyb, forw);
298 for (i=0;i<8;i++) {
299 out[i] = 0;
302 for (i=0;i<64;i++) {
303 if (outb[i])
304 out[i/8] |= (1<<(7-(i%8)));
308 void E_P16(unsigned char *p14,unsigned char *p16)
310 unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
311 smbhash(p16, sp8, p14, 1);
312 smbhash(p16+8, sp8, p14+7, 1);
315 void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
317 smbhash(p24, c8, p21, 1);
318 smbhash(p24+8, c8, p21+7, 1);
319 smbhash(p24+16, c8, p21+14, 1);
322 void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
324 smbhash(out, in, p14, 0);
325 smbhash(out+8, in+8, p14+7, 0);
328 void E_old_pw_hash( unsigned char *p14, unsigned char *in, unsigned char *out)
330 smbhash(out, in, p14, 1);
331 smbhash(out+8, in+8, p14+7, 1);
334 void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
336 unsigned char buf[8];
338 smbhash(buf, in, key, 1);
339 smbhash(out, buf, key+9, 1);
342 void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
344 unsigned char buf[8];
345 static unsigned char key2[8];
347 smbhash(buf, in, key, 1);
348 key2[0] = key[7];
349 smbhash(out, buf, key2, 1);
352 void cred_hash3(unsigned char *out,unsigned char *in,unsigned char *key, int forw)
354 static unsigned char key2[8];
356 smbhash(out, in, key, forw);
357 key2[0] = key[7];
358 smbhash(out + 8, in + 8, key2, forw);
361 void SamOEMhash( unsigned char *data, unsigned char *key, int val)
363 unsigned char s_box[256];
364 unsigned char index_i = 0;
365 unsigned char index_j = 0;
366 unsigned char j = 0;
367 int ind;
369 for (ind = 0; ind < 256; ind++)
371 s_box[ind] = (unsigned char)ind;
374 for( ind = 0; ind < 256; ind++)
376 unsigned char tc;
378 j += (s_box[ind] + key[ind%16]);
380 tc = s_box[ind];
381 s_box[ind] = s_box[j];
382 s_box[j] = tc;
384 for( ind = 0; ind < (val ? 516 : 16); ind++)
386 unsigned char tc;
387 unsigned char t;
389 index_i++;
390 index_j += s_box[index_i];
392 tc = s_box[index_i];
393 s_box[index_i] = s_box[index_j];
394 s_box[index_j] = tc;
396 t = s_box[index_i] + s_box[index_j];
397 data[ind] = data[ind] ^ s_box[t];