2 Unix SMB/CIFS implementation.
4 a partial implementation of DES designed for use in the
5 SMB authentication protocol
7 Copyright (C) Andrew Tridgell 1998
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 This code makes no attempt to be fast! In fact, it is a very
36 This code is NOT a complete DES implementation. It implements only
37 the minimum necessary for SMB authentication, as used by all SMB
38 products (including every copy of Microsoft Windows95 ever sold)
40 In particular, it can only do a unchained forward DES pass. This
41 means it is not possible to use this code for encryption/decryption
42 of data, instead it is only useful as a "hash" algorithm.
44 There is no entry point into this code that allows normal DES operation.
46 I believe this means that this code does not come under ITAR
47 regulations but this is NOT a legal opinion. If you are concerned
48 about the applicability of ITAR regulations to this code then you
49 should confirm it for yourself (and maybe let me know if you come
50 up with a different answer to the one above)
54 #define uchar unsigned char
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};
65 static const uchar perm2
[48] = {14, 17, 11, 24, 1, 5,
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};
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};
83 static const uchar perm4
[48] = { 32, 1, 2, 3, 4, 5,
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};
92 static const uchar perm5
[32] = { 16, 7, 20, 21,
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};
112 static const uchar sc
[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}}};
155 static void permute(char *out
, const char *in
, const uchar
*p
, int n
)
162 static void lshift(char *d
, int count
, int n
)
167 out
[i
] = d
[(i
+count
)%n
];
172 static void concat(char *out
, char *in1
, char *in2
, int l1
, int l2
)
180 static void exor(char *out
, char *in1
, char *in2
, int n
)
184 out
[i
] = in1
[i
] ^ in2
[i
];
187 static void dohash(char *out
, char *in
, char *key
, int forw
)
199 permute(pk1
, key
, perm1
, 56);
207 lshift(c
, sc
[i
], 28);
208 lshift(d
, sc
[i
], 28);
210 concat(cd
, c
, d
, 28, 28);
211 permute(ki
[i
], cd
, perm2
, 48);
214 permute(pd1
, in
, perm3
, 64);
229 permute(er
, r
, perm4
, 48);
231 exor(erk
, er
, ki
[forw
? i
: 15 - i
], 48);
235 b
[j
][k
] = erk
[j
*6 + k
];
239 m
= (b
[j
][0]<<1) | b
[j
][5];
241 n
= (b
[j
][1]<<3) | (b
[j
][2]<<2) | (b
[j
][3]<<1) | b
[j
][4];
244 b
[j
][k
] = (sbox
[j
][m
][n
] & (1<<(3-k
)))?1:0;
250 permute(pcb
, cb
, perm5
, 32);
252 exor(r2
, l
, pcb
, 32);
261 concat(rl
, r
, l
, 32, 32);
263 permute(out
, rl
, perm6
, 64);
266 static void str_to_key(const unsigned char *str
,unsigned char *key
)
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;
279 key
[i
] = (key
[i
]<<1);
284 void crypt_des_ecb(unsigned char *out
, const unsigned char *in
, const unsigned char *key
, int forw
)
290 unsigned char key2
[8];
292 str_to_key(key
, key2
);
295 inb
[i
] = (in
[i
/8] & (1<<(7-(i
%8)))) ? 1 : 0;
296 keyb
[i
] = (key2
[i
/8] & (1<<(7-(i
%8)))) ? 1 : 0;
300 dohash(outb
, inb
, keyb
, forw
);
308 out
[i
/8] |= (1<<(7-(i
%8)));