linux/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)[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        ki = kmalloc(16*48, GFP_KERNEL);
 209        if (ki == NULL) {
 210                kfree(pk1);
 211                return;
 212        }
 213
 214        cd = pk1 + 56;
 215        pd1 = cd  + 56;
 216        rl = pd1 + 64;
 217
 218        permute(pk1, key, perm1, 56);
 219
 220        for (i = 0; i < 28; i++)
 221                c[i] = pk1[i];
 222        for (i = 0; i < 28; i++)
 223                d[i] = pk1[i + 28];
 224
 225        for (i = 0; i < 16; i++) {
 226                lshift(c, sc[i], 28);
 227                lshift(d, sc[i], 28);
 228
 229                concat(cd, c, d, 28, 28);
 230                permute(ki[i], cd, perm2, 48);
 231        }
 232
 233        permute(pd1, in, perm3, 64);
 234
 235        for (j = 0; j < 32; j++) {
 236                l[j] = pd1[j];
 237                r[j] = pd1[j + 32];
 238        }
 239
 240        for (i = 0; i < 16; i++) {
 241                char *er;  /* er[48]  */
 242                char *erk; /* erk[48] */
 243                char b[8][6];
 244                char *cb;  /* cb[32]  */
 245                char *pcb; /* pcb[32] */
 246                char *r2;  /* r2[32]  */
 247
 248                er = kmalloc(48+48+32+32+32, GFP_KERNEL);
 249                if (er == NULL) {
 250                        kfree(pk1);
 251                        kfree(ki);
 252                        return;
 253                }
 254                erk = er+48;
 255                cb  = erk+48;
 256                pcb = cb+32;
 257                r2  = pcb+32;
 258
 259                permute(er, r, perm4, 48);
 260
 261                xor(erk, er, ki[forw ? i : 15 - i], 48);
 262
 263                for (j = 0; j < 8; j++)
 264                        for (k = 0; k < 6; k++)
 265                                b[j][k] = erk[j * 6 + k];
 266
 267                for (j = 0; j < 8; j++) {
 268                        int m, n;
 269                        m = (b[j][0] << 1) | b[j][5];
 270
 271                        n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
 272                                                               1) | b[j][4];
 273
 274                        for (k = 0; k < 4; k++)
 275                                b[j][k] =
 276                                    (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
 277                }
 278
 279                for (j = 0; j < 8; j++)
 280                        for (k = 0; k < 4; k++)
 281                                cb[j * 4 + k] = b[j][k];
 282                permute(pcb, cb, perm5, 32);
 283
 284                xor(r2, l, pcb, 32);
 285
 286                for (j = 0; j < 32; j++)
 287                        l[j] = r[j];
 288
 289                for (j = 0; j < 32; j++)
 290                        r[j] = r2[j];
 291
 292                kfree(er);
 293        }
 294
 295        concat(rl, r, l, 32, 32);
 296
 297        permute(out, rl, perm6, 64);
 298        kfree(pk1);
 299        kfree(ki);
 300}
 301
 302static void
 303str_to_key(unsigned char *str, unsigned char *key)
 304{
 305        int i;
 306
 307        key[0] = str[0] >> 1;
 308        key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
 309        key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
 310        key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
 311        key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
 312        key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
 313        key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
 314        key[7] = str[6] & 0x7F;
 315        for (i = 0; i < 8; i++)
 316                key[i] = (key[i] << 1);
 317}
 318
 319static void
 320smbhash(unsigned char *out, const unsigned char *in, unsigned char *key,
 321        int forw)
 322{
 323        int i;
 324        char *outb; /* outb[64] */
 325        char *inb;  /* inb[64]  */
 326        char *keyb; /* keyb[64] */
 327        unsigned char key2[8];
 328
 329        outb = kmalloc(64 * 3, GFP_KERNEL);
 330        if (outb == NULL)
 331                return;
 332
 333        inb  = outb + 64;
 334        keyb = inb +  64;
 335
 336        str_to_key(key, key2);
 337
 338        for (i = 0; i < 64; i++) {
 339                inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
 340                keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
 341                outb[i] = 0;
 342        }
 343
 344        dohash(outb, inb, keyb, forw);
 345
 346        for (i = 0; i < 8; i++)
 347                out[i] = 0;
 348
 349        for (i = 0; i < 64; i++) {
 350                if (outb[i])
 351                        out[i / 8] |= (1 << (7 - (i % 8)));
 352        }
 353        kfree(outb);
 354}
 355
 356void
 357E_P16(unsigned char *p14, unsigned char *p16)
 358{
 359        unsigned char sp8[8] =
 360            { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
 361        smbhash(p16, sp8, p14, 1);
 362        smbhash(p16 + 8, sp8, p14 + 7, 1);
 363}
 364
 365void
 366E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
 367{
 368        smbhash(p24, c8, p21, 1);
 369        smbhash(p24 + 8, c8, p21 + 7, 1);
 370        smbhash(p24 + 16, c8, p21 + 14, 1);
 371}
 372
 373#if 0 /* currently unused */
 374static void
 375D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
 376{
 377        smbhash(out, in, p14, 0);
 378        smbhash(out + 8, in + 8, p14 + 7, 0);
 379}
 380
 381static void
 382E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
 383{
 384        smbhash(out, in, p14, 1);
 385        smbhash(out + 8, in + 8, p14 + 7, 1);
 386}
 387/* these routines are currently unneeded, but may be
 388        needed later */
 389void
 390cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
 391{
 392        unsigned char buf[8];
 393
 394        smbhash(buf, in, key, 1);
 395        smbhash(out, buf, key + 9, 1);
 396}
 397
 398void
 399cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
 400{
 401        unsigned char buf[8];
 402        static unsigned char key2[8];
 403
 404        smbhash(buf, in, key, 1);
 405        key2[0] = key[7];
 406        smbhash(out, buf, key2, 1);
 407}
 408
 409void
 410cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
 411{
 412        static unsigned char key2[8];
 413
 414        smbhash(out, in, key, forw);
 415        key2[0] = key[7];
 416        smbhash(out + 8, in + 8, key2, forw);
 417}
 418#endif /* unneeded routines */
 419