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#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
 374#if 0 /* currently unsued */
 375static void
 376D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
 377{
 378        smbhash(out, in, p14, 0);
 379        smbhash(out + 8, in + 8, p14 + 7, 0);
 380}
 381
 382static void
 383E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
 384{
 385        smbhash(out, in, p14, 1);
 386        smbhash(out + 8, in + 8, p14 + 7, 1);
 387}
 388/* these routines are currently unneeded, but may be
 389        needed later */
 390void
 391cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
 392{
 393        unsigned char buf[8];
 394
 395        smbhash(buf, in, key, 1);
 396        smbhash(out, buf, key + 9, 1);
 397}
 398
 399void
 400cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
 401{
 402        unsigned char buf[8];
 403        static unsigned char key2[8];
 404
 405        smbhash(buf, in, key, 1);
 406        key2[0] = key[7];
 407        smbhash(out, buf, key2, 1);
 408}
 409
 410void
 411cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
 412{
 413        static unsigned char key2[8];
 414
 415        smbhash(out, in, key, forw);
 416        key2[0] = key[7];
 417        smbhash(out + 8, in + 8, key2, forw);
 418}
 419#endif /* unneeded routines */
 420