1/* 2 Unix SMB/Netbios implementation. 3 Version 1.9. 4 5 a partial implementation of DES designed for use in the 6 SMB authentication protocol 7 8 Copyright (C) Andrew Tridgell 1998 9 Modified by Steve French (sfrench@us.ibm.com) 2002,2004 10 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. 15 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. 20 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. 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#include <linux/slab.h> 48#include "cifsencrypt.h" 49#define uchar unsigned char 50 51static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, 52 1, 58, 50, 42, 34, 26, 18, 53 10, 2, 59, 51, 43, 35, 27, 54 19, 11, 3, 60, 52, 44, 36, 55 63, 55, 47, 39, 31, 23, 15, 56 7, 62, 54, 46, 38, 30, 22, 57 14, 6, 61, 53, 45, 37, 29, 58 21, 13, 5, 28, 20, 12, 4 59}; 60 61static 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 69}; 70 71static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2, 72 60, 52, 44, 36, 28, 20, 12, 4, 73 62, 54, 46, 38, 30, 22, 14, 6, 74 64, 56, 48, 40, 32, 24, 16, 8, 75 57, 49, 41, 33, 25, 17, 9, 1, 76 59, 51, 43, 35, 27, 19, 11, 3, 77 61, 53, 45, 37, 29, 21, 13, 5, 78 63, 55, 47, 39, 31, 23, 15, 7 79}; 80 81static uchar perm4[48] = { 32, 1, 2, 3, 4, 5, 82 4, 5, 6, 7, 8, 9, 83 8, 9, 10, 11, 12, 13, 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 89}; 90 91static uchar perm5[32] = { 16, 7, 20, 21, 92 29, 12, 28, 17, 93 1, 15, 23, 26, 94 5, 18, 31, 10, 95 2, 8, 24, 14, 96 32, 27, 3, 9, 97 19, 13, 30, 6, 98 22, 11, 4, 25 99}; 100 101static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32, 102 39, 7, 47, 15, 55, 23, 63, 31, 103 38, 6, 46, 14, 54, 22, 62, 30, 104 37, 5, 45, 13, 53, 21, 61, 29, 105 36, 4, 44, 12, 52, 20, 60, 28, 106 35, 3, 43, 11, 51, 19, 59, 27, 107 34, 2, 42, 10, 50, 18, 58, 26, 108 33, 1, 41, 9, 49, 17, 57, 25 109}; 110 111static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; 112 113static uchar sbox[8][4][16] = { 114 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, 115 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, 116 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, 117 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} }, 118 119 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, 120 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, 121 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, 122 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} }, 123 124 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, 125 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, 126 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, 127 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} }, 128 129 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, 130 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, 131 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, 132 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} }, 133 134 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, 135 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, 136 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, 137 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} }, 138 139 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, 140 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, 141 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, 142 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} }, 143 144 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, 145 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, 146 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, 147 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} }, 148 149 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, 150 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, 151 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, 152 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} } 153}; 154 155static void 156permute(char *out, char *in, uchar *p, int n) 157{ 158 int i; 159 for (i = 0; i < n; i++) 160 out[i] = in[p[i] - 1]; 161} 162 163static void 164lshift(char *d, int count, int n) 165{ 166 char out[64]; 167 int i; 168 for (i = 0; i < n; i++) 169 out[i] = d[(i + count) % n]; 170 for (i = 0; i < n; i++) 171 d[i] = out[i]; 172} 173 174static void 175concat(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 183static void 184xor(char *out, char *in1, char *in2, int n) 185{ 186 int i; 187 for (i = 0; i < n; i++) 188 out[i] = in1[i] ^ in2[i]; 189} 190 191static void 192dohash(char *out, char *in, char *key, int forw) 193{ 194 int i, j, k; 195 char *pk1; 196 char c[28]; 197 char d[28]; 198 char *cd; 199 char (*ki)[48]; 200 char *pd1; 201 char l[32], r[32]; 202 char *rl; 203 204 /* Have to reduce stack usage */ 205 pk1 = kmalloc(56+56+64+64, GFP_KERNEL); 206 if (pk1 == NULL) 207 return; 208 209 ki = kmalloc(16*48, GFP_KERNEL); 210 if (ki == NULL) { 211 kfree(pk1); 212 return; 213 } 214 215 cd = pk1 + 56; 216 pd1 = cd + 56; 217 rl = pd1 + 64; 218 219 permute(pk1, key, perm1, 56); 220 221 for (i = 0; i < 28; i++) 222 c[i] = pk1[i]; 223 for (i = 0; i < 28; i++) 224 d[i] = pk1[i + 28]; 225 226 for (i = 0; i < 16; i++) { 227 lshift(c, sc[i], 28); 228 lshift(d, sc[i], 28); 229 230 concat(cd, c, d, 28, 28); 231 permute(ki[i], cd, perm2, 48); 232 } 233 234 permute(pd1, in, perm3, 64); 235 236 for (j = 0; j < 32; j++) { 237 l[j] = pd1[j]; 238 r[j] = pd1[j + 32]; 239 } 240 241 for (i = 0; i < 16; i++) { 242 char *er; /* er[48] */ 243 char *erk; /* erk[48] */ 244 char b[8][6]; 245 char *cb; /* cb[32] */ 246 char *pcb; /* pcb[32] */ 247 char *r2; /* r2[32] */ 248 249 er = kmalloc(48+48+32+32+32, GFP_KERNEL); 250 if (er == NULL) { 251 kfree(pk1); 252 kfree(ki); 253 return; 254 } 255 erk = er+48; 256 cb = erk+48; 257 pcb = cb+32; 258 r2 = pcb+32; 259 260 permute(er, r, perm4, 48); 261 262 xor(erk, er, ki[forw ? i : 15 - i], 48); 263 264 for (j = 0; j < 8; j++) 265 for (k = 0; k < 6; k++) 266 b[j][k] = erk[j * 6 + k]; 267 268 for (j = 0; j < 8; j++) { 269 int m, n; 270 m = (b[j][0] << 1) | b[j][5]; 271 272 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 273 1) | b[j][4]; 274 275 for (k = 0; k < 4; k++) 276 b[j][k] = 277 (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0; 278 } 279 280 for (j = 0; j < 8; j++) 281 for (k = 0; k < 4; k++) 282 cb[j * 4 + k] = b[j][k]; 283 permute(pcb, cb, perm5, 32); 284 285 xor(r2, l, pcb, 32); 286 287 for (j = 0; j < 32; j++) 288 l[j] = r[j]; 289 290 for (j = 0; j < 32; j++) 291 r[j] = r2[j]; 292 293 kfree(er); 294 } 295 296 concat(rl, r, l, 32, 32); 297 298 permute(out, rl, perm6, 64); 299 kfree(pk1); 300 kfree(ki); 301} 302 303static void 304str_to_key(unsigned char *str, unsigned char *key) 305{ 306 int i; 307 308 key[0] = str[0] >> 1; 309 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); 310 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); 311 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); 312 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); 313 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); 314 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); 315 key[7] = str[6] & 0x7F; 316 for (i = 0; i < 8; i++) 317 key[i] = (key[i] << 1); 318} 319 320static void 321smbhash(unsigned char *out, const unsigned char *in, unsigned char *key, 322 int forw) 323{ 324 int i; 325 char *outb; /* outb[64] */ 326 char *inb; /* inb[64] */ 327 char *keyb; /* keyb[64] */ 328 unsigned char key2[8]; 329 330 outb = kmalloc(64 * 3, GFP_KERNEL); 331 if (outb == NULL) 332 return; 333 334 inb = outb + 64; 335 keyb = inb + 64; 336 337 str_to_key(key, key2); 338 339 for (i = 0; i < 64; i++) { 340 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; 341 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; 342 outb[i] = 0; 343 } 344 345 dohash(outb, inb, keyb, forw); 346 347 for (i = 0; i < 8; i++) 348 out[i] = 0; 349 350 for (i = 0; i < 64; i++) { 351 if (outb[i]) 352 out[i / 8] |= (1 << (7 - (i % 8))); 353 } 354 kfree(outb); 355} 356 357void 358E_P16(unsigned char *p14, unsigned char *p16) 359{ 360 unsigned char sp8[8] = 361 { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; 362 smbhash(p16, sp8, p14, 1); 363 smbhash(p16 + 8, sp8, p14 + 7, 1); 364} 365 366void 367E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) 368{ 369 smbhash(p24, c8, p21, 1); 370 smbhash(p24 + 8, c8, p21 + 7, 1); 371 smbhash(p24 + 16, c8, p21 + 14, 1); 372} 373