linux-bk/fs/cifs/smbdes.c
<<
>>
Prefs
   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#define uchar unsigned char
  49
  50static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
  51        1, 58, 50, 42, 34, 26, 18,
  52        10, 2, 59, 51, 43, 35, 27,
  53        19, 11, 3, 60, 52, 44, 36,
  54        63, 55, 47, 39, 31, 23, 15,
  55        7, 62, 54, 46, 38, 30, 22,
  56        14, 6, 61, 53, 45, 37, 29,
  57        21, 13, 5, 28, 20, 12, 4
  58};
  59
  60static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
  61        3, 28, 15, 6, 21, 10,
  62        23, 19, 12, 4, 26, 8,
  63        16, 7, 27, 20, 13, 2,
  64        41, 52, 31, 37, 47, 55,
  65        30, 40, 51, 45, 33, 48,
  66        44, 49, 39, 56, 34, 53,
  67        46, 42, 50, 36, 29, 32
  68};
  69
  70static 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
  78};
  79
  80static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
  81        4, 5, 6, 7, 8, 9,
  82        8, 9, 10, 11, 12, 13,
  83        12, 13, 14, 15, 16, 17,
  84        16, 17, 18, 19, 20, 21,
  85        20, 21, 22, 23, 24, 25,
  86        24, 25, 26, 27, 28, 29,
  87        28, 29, 30, 31, 32, 1
  88};
  89
  90static uchar perm5[32] = { 16, 7, 20, 21,
  91        29, 12, 28, 17,
  92        1, 15, 23, 26,
  93        5, 18, 31, 10,
  94        2, 8, 24, 14,
  95        32, 27, 3, 9,
  96        19, 13, 30, 6,
  97        22, 11, 4, 25
  98};
  99
 100static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
 101        39, 7, 47, 15, 55, 23, 63, 31,
 102        38, 6, 46, 14, 54, 22, 62, 30,
 103        37, 5, 45, 13, 53, 21, 61, 29,
 104        36, 4, 44, 12, 52, 20, 60, 28,
 105        35, 3, 43, 11, 51, 19, 59, 27,
 106        34, 2, 42, 10, 50, 18, 58, 26,
 107        33, 1, 41, 9, 49, 17, 57, 25
 108};
 109
 110static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
 111
 112static uchar sbox[8][4][16] = {
 113        {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
 114         {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
 115         {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
 116         {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
 117
 118        {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
 119         {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
 120         {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
 121         {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
 122
 123        {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
 124         {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
 125         {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
 126         {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
 127
 128        {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
 129         {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
 130         {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
 131         {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
 132
 133        {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
 134         {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
 135         {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
 136         {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
 137
 138        {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
 139         {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
 140         {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
 141         {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
 142
 143        {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
 144         {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
 145         {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
 146         {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
 147
 148        {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
 149         {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
 150         {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
 151         {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
 152};
 153
 154static void
 155permute(char *out, char *in, uchar * p, int n)
 156{
 157        int i;
 158        for (i = 0; i < n; i++)
 159                out[i] = in[p[i] - 1];
 160}
 161
 162static void
 163lshift(char *d, int count, int n)
 164{
 165        char out[64];
 166        int i;
 167        for (i = 0; i < n; i++)
 168                out[i] = d[(i + count) % n];
 169        for (i = 0; i < n; i++)
 170                d[i] = out[i];
 171}
 172
 173static void
 174concat(char *out, char *in1, char *in2, int l1, int l2)
 175{
 176        while (l1--)
 177                *out++ = *in1++;
 178        while (l2--)
 179                *out++ = *in2++;
 180}
 181
 182static void
 183xor(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
 190static void
 191dohash(char *out, char *in, char *key, int forw)
 192{
 193        int i, j, k;
 194        char *pk1;
 195        char c[28];
 196        char d[28];
 197        char *cd;
 198        char ki[16][48];
 199        char *pd1;
 200        char l[32], r[32];
 201        char *rl;
 202
 203        /* Have to reduce stack usage */
 204        pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
 205        if(pk1 == NULL)
 206                return;
 207
 208        cd = pk1 + 56;
 209        pd1= cd  + 56;
 210        rl = pd1 + 64;
 211
 212        permute(pk1, key, perm1, 56);
 213
 214        for (i = 0; i < 28; i++)
 215                c[i] = pk1[i];
 216        for (i = 0; i < 28; i++)
 217                d[i] = pk1[i + 28];
 218
 219        for (i = 0; i < 16; i++) {
 220                lshift(c, sc[i], 28);
 221                lshift(d, sc[i], 28);
 222
 223                concat(cd, c, d, 28, 28);
 224                permute(ki[i], cd, perm2, 48);
 225        }
 226
 227        permute(pd1, in, perm3, 64);
 228
 229        for (j = 0; j < 32; j++) {
 230                l[j] = pd1[j];
 231                r[j] = pd1[j + 32];
 232        }
 233
 234        for (i = 0; i < 16; i++) {
 235                char *er;  /* er[48]  */
 236                char *erk; /* erk[48] */
 237                char b[8][6];
 238                char *cb;  /* cb[32]  */
 239                char *pcb; /* pcb[32] */
 240                char *r2;  /* r2[32]  */
 241
 242                er = kmalloc(48+48+32+32+32, GFP_KERNEL);
 243                if(er == NULL) {
 244                        kfree(pk1);
 245                        return;
 246                }
 247                erk = er+48;
 248                cb  = erk+48;
 249                pcb = cb+32;
 250                r2  = pcb+32;
 251
 252                permute(er, r, perm4, 48);
 253
 254                xor(erk, er, ki[forw ? i : 15 - i], 48);
 255
 256                for (j = 0; j < 8; j++)
 257                        for (k = 0; k < 6; k++)
 258                                b[j][k] = erk[j * 6 + k];
 259
 260                for (j = 0; j < 8; j++) {
 261                        int m, n;
 262                        m = (b[j][0] << 1) | b[j][5];
 263
 264                        n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
 265                                                               1) | b[j][4];
 266
 267                        for (k = 0; k < 4; k++)
 268                                b[j][k] =
 269                                    (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
 270                }
 271
 272                for (j = 0; j < 8; j++)
 273                        for (k = 0; k < 4; k++)
 274                                cb[j * 4 + k] = b[j][k];
 275                permute(pcb, cb, perm5, 32);
 276
 277                xor(r2, l, pcb, 32);
 278
 279                for (j = 0; j < 32; j++)
 280                        l[j] = r[j];
 281
 282                for (j = 0; j < 32; j++)
 283                        r[j] = r2[j];
 284
 285                kfree(er);
 286        }
 287
 288        concat(rl, r, l, 32, 32);
 289
 290        permute(out, rl, perm6, 64);
 291        kfree(pk1);
 292}
 293
 294static void
 295str_to_key(unsigned char *str, unsigned char *key)
 296{
 297        int i;
 298
 299        key[0] = str[0] >> 1;
 300        key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
 301        key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
 302        key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
 303        key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
 304        key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
 305        key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
 306        key[7] = str[6] & 0x7F;
 307        for (i = 0; i < 8; i++) {
 308                key[i] = (key[i] << 1);
 309        }
 310}
 311
 312static void
 313smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
 314{
 315        int i;
 316        char *outb; /* outb[64] */
 317        char *inb;  /* inb[64]  */
 318        char *keyb; /* keyb[64] */
 319        unsigned char key2[8];
 320
 321        outb = kmalloc(64 * 3,GFP_KERNEL);
 322        if(outb == NULL)
 323                return;
 324
 325        inb  = outb + 64;
 326        keyb = inb +  64;
 327
 328        str_to_key(key, key2);
 329
 330        for (i = 0; i < 64; i++) {
 331                inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
 332                keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
 333                outb[i] = 0;
 334        }
 335
 336        dohash(outb, inb, keyb, forw);
 337
 338        for (i = 0; i < 8; i++) {
 339                out[i] = 0;
 340        }
 341
 342        for (i = 0; i < 64; i++) {
 343                if (outb[i])
 344                        out[i / 8] |= (1 << (7 - (i % 8)));
 345        }
 346        kfree(outb);
 347}
 348
 349void
 350E_P16(unsigned char *p14, unsigned char *p16)
 351{
 352        unsigned char sp8[8] =
 353            { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
 354        smbhash(p16, sp8, p14, 1);
 355        smbhash(p16 + 8, sp8, p14 + 7, 1);
 356}
 357
 358void
 359E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
 360{
 361        smbhash(p24, c8, p21, 1);
 362        smbhash(p24 + 8, c8, p21 + 7, 1);
 363        smbhash(p24 + 16, c8, p21 + 14, 1);
 364}
 365
 366void
 367D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
 368{
 369        smbhash(out, in, p14, 0);
 370        smbhash(out + 8, in + 8, p14 + 7, 0);
 371}
 372
 373void
 374E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
 375{
 376        smbhash(out, in, p14, 1);
 377        smbhash(out + 8, in + 8, p14 + 7, 1);
 378}
 379
 380void
 381cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
 382{
 383        unsigned char buf[8];
 384
 385        smbhash(buf, in, key, 1);
 386        smbhash(out, buf, key + 9, 1);
 387}
 388
 389void
 390cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
 391{
 392        unsigned char buf[8];
 393        static unsigned char key2[8];
 394
 395        smbhash(buf, in, key, 1);
 396        key2[0] = key[7];
 397        smbhash(out, buf, key2, 1);
 398}
 399
 400void
 401cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
 402{
 403        static unsigned char key2[8];
 404
 405        smbhash(out, in, key, forw);
 406        key2[0] = key[7];
 407        smbhash(out + 8, in + 8, key2, forw);
 408}
 409
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.