Modified revamp of the libsmbclient interface.
[samba.git] / source / libsmb / smbdes.c
index b62a160418df31d8fe5dcbbc2cddb2adff37cad2..98d5cd05b7e1c9c8eabf7c8bbab6ea3b12ad0775 100644 (file)
@@ -1,15 +1,14 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
 
    a partial implementation of DES designed for use in the 
    SMB authentication protocol
 
-   Copyright (C) Andrew Tridgell 1997
+   Copyright (C) Andrew Tridgell 1998
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "includes.h"
 
 /* NOTES: 
 
@@ -46,8 +45,9 @@
 */
 
 
+#define uchar unsigned char
 
-static int perm1[56] = {57, 49, 41, 33, 25, 17,  9,
+static const uchar perm1[56] = {57, 49, 41, 33, 25, 17,  9,
                         1, 58, 50, 42, 34, 26, 18,
                        10,  2, 59, 51, 43, 35, 27,
                        19, 11,  3, 60, 52, 44, 36,
@@ -56,7 +56,7 @@ static int perm1[56] = {57, 49, 41, 33, 25, 17,  9,
                        14,  6, 61, 53, 45, 37, 29,
                        21, 13,  5, 28, 20, 12,  4};
 
-static int perm2[48] = {14, 17, 11, 24,  1,  5,
+static const uchar perm2[48] = {14, 17, 11, 24,  1,  5,
                          3, 28, 15,  6, 21, 10,
                         23, 19, 12,  4, 26,  8,
                         16,  7, 27, 20, 13,  2,
@@ -65,7 +65,7 @@ static int perm2[48] = {14, 17, 11, 24,  1,  5,
                         44, 49, 39, 56, 34, 53,
                         46, 42, 50, 36, 29, 32};
 
-static int perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
+static const uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
                        60, 52, 44, 36, 28, 20, 12,  4,
                        62, 54, 46, 38, 30, 22, 14,  6,
                        64, 56, 48, 40, 32, 24, 16,  8,
@@ -74,7 +74,7 @@ static int perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
                        61, 53, 45, 37, 29, 21, 13,  5,
                        63, 55, 47, 39, 31, 23, 15,  7};
 
-static int perm4[48] = {   32,  1,  2,  3,  4,  5,
+static const uchar perm4[48] = {   32,  1,  2,  3,  4,  5,
                             4,  5,  6,  7,  8,  9,
                             8,  9, 10, 11, 12, 13,
                            12, 13, 14, 15, 16, 17,
@@ -83,7 +83,7 @@ static int perm4[48] = {   32,  1,  2,  3,  4,  5,
                            24, 25, 26, 27, 28, 29,
                            28, 29, 30, 31, 32,  1};
 
-static int perm5[32] = {      16,  7, 20, 21,
+static const uchar perm5[32] = {      16,  7, 20, 21,
                               29, 12, 28, 17,
                                1, 15, 23, 26,
                                5, 18, 31, 10,
@@ -93,7 +93,7 @@ static int perm5[32] = {      16,  7, 20, 21,
                               22, 11,  4, 25};
 
 
-static int perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
+static const uchar perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
                         39,  7, 47, 15, 55, 23, 63, 31,
                         38,  6, 46, 14, 54, 22, 62, 30,
                         37,  5, 45, 13, 53, 21, 61, 29,
@@ -103,9 +103,9 @@ static int perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
                         33,  1, 41,  9, 49, 17, 57, 25};
 
 
-static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+static const uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
 
-static int sbox[8][4][16] = {
+static const uchar sbox[8][4][16] = {
        {{14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},
         {0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},
         {4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},
@@ -146,7 +146,7 @@ static int sbox[8][4][16] = {
         {7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},
         {2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}}};
 
-static void permute(char *out, char *in, int *p, int n)
+static void permute(char *out, const char *in, const uchar *p, int n)
 {
        int i;
        for (i=0;i<n;i++)
@@ -171,14 +171,14 @@ static void concat(char *out, char *in1, char *in2, int l1, int l2)
                *out++ = *in2++;
 }
 
-static void xor(char *out, char *in1, char *in2, int n)
+static void x_or(char *out, char *in1, char *in2, int n)
 {
        int i;
        for (i=0;i<n;i++)
                out[i] = in1[i] ^ in2[i];
 }
 
-static void dohash(char *out, char *in, char *key)
+static void dohash(char *out, char *in, char *key, int forw)
 {
        int i, j, k;
        char pk1[56];
@@ -222,7 +222,7 @@ static void dohash(char *out, char *in, char *key)
 
                permute(er, r, perm4, 48);
 
-               xor(erk, er, ki[i], 48);
+               x_or(erk, er, ki[forw ? i : 15 - i], 48);
 
                for (j=0;j<8;j++)
                        for (k=0;k<6;k++)
@@ -243,7 +243,7 @@ static void dohash(char *out, char *in, char *key)
                                cb[j*4+k] = b[j][k];
                permute(pcb, cb, perm5, 32);
 
-               xor(r2, l, pcb, 32);
+               x_or(r2, l, pcb, 32);
 
                for (j=0;j<32;j++)
                        l[j] = r[j];
@@ -257,7 +257,8 @@ static void dohash(char *out, char *in, char *key)
        permute(out, rl, perm6, 64);
 }
 
-void str_to_key(unsigned char *str,unsigned char *key)
+/* Convert a 7 byte string to an 8 byte key. */
+static void str_to_key(const unsigned char str[7], unsigned char key[8])
 {
        int i;
 
@@ -275,7 +276,7 @@ void str_to_key(unsigned char *str,unsigned char *key)
 }
 
 
-void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
+void des_crypt56(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw)
 {
        int i;
        char outb[64];
@@ -291,7 +292,7 @@ void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
                outb[i] = 0;
        }
 
-       dohash(outb, inb, keyb);
+       dohash(outb, inb, keyb, forw);
 
        for (i=0;i<8;i++) {
                out[i] = 0;
@@ -303,18 +304,117 @@ void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
        }
 }
 
-void E_P16(unsigned char *p14,unsigned char *p16)
+void E_P16(const unsigned char *p14,unsigned char *p16)
 {
        unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
-       smbhash(p16, sp8, p14);
-       smbhash(p16+8, sp8, p14+7);
+       des_crypt56(p16, sp8, p14, 1);
+       des_crypt56(p16+8, sp8, p14+7, 1);
 }
 
-void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+void E_P24(const unsigned char *p21, const unsigned char *c8, unsigned char *p24)
 {
-       smbhash(p24, c8, p21);
-       smbhash(p24+8, c8, p21+7);
-       smbhash(p24+16, c8, p21+14);
+       des_crypt56(p24, c8, p21, 1);
+       des_crypt56(p24+8, c8, p21+7, 1);
+       des_crypt56(p24+16, c8, p21+14, 1);
 }
 
+void D_P16(const unsigned char *p14, const unsigned char *in, unsigned char *out)
+{
+       des_crypt56(out, in, p14, 0);
+        des_crypt56(out+8, in+8, p14+7, 0);
+}
+
+void E_old_pw_hash( unsigned char *p14, const unsigned char *in, unsigned char *out)
+{
+        des_crypt56(out, in, p14, 1);
+        des_crypt56(out+8, in+8, p14+7, 1);
+}
+
+/* forward des encryption with a 128 bit key */
+void des_crypt128(unsigned char out[8], const unsigned char in[8], const unsigned char key[16])
+{
+       unsigned char buf[8];
+
+       des_crypt56(buf, in, key, 1);
+       des_crypt56(out, buf, key+9, 1);
+}
+
+/* forward des encryption with a 64 bit key */
+void des_crypt64(unsigned char out[8], const unsigned char in[8], const unsigned char key[8])
+{
+       unsigned char buf[8];
+       unsigned char key2[8];
+
+       memset(key2,'\0',8);
+       des_crypt56(buf, in, key, 1);
+       key2[0] = key[7];
+       des_crypt56(out, buf, key2, 1);
+}
+
+/* des encryption with a 112 bit (14 byte) key */
+/* Note that if the forw is 1, and key is actually 8 bytes of key, followed by 6 bytes of zeros,
+   this is identical to des_crypt64(). JRA. */
+
+void des_crypt112(unsigned char out[8], const unsigned char in[8], const unsigned char key[14], int forw)
+{
+       unsigned char buf[8];
+       des_crypt56(buf, in, key, forw);
+       des_crypt56(out, buf, key+7, forw);
+}
+
+void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw)
+{
+        unsigned char key2[8];
 
+       memset(key2,'\0',8);
+        des_crypt56(out, in, key, forw);
+        key2[0] = key[7];
+        des_crypt56(out + 8, in + 8, key2, forw);
+}
+
+/* des encryption of a 16 byte lump of data with a 112 bit key */
+/* Note that if the key is actually 8 bytes of key, followed by 6 bytes of zeros,
+   this is identical to cred_hash3(). JRA. */
+
+void des_crypt112_16(unsigned char out[16], unsigned char in[16], const unsigned char key[14], int forw)
+{
+       des_crypt56(out, in, key, forw);
+       des_crypt56(out + 8, in + 8, key+7, forw);
+}
+
+/*****************************************************************
+ arc4 crypt/decrypt with a 16 byte key.
+*****************************************************************/
+
+void SamOEMhash( unsigned char *data, const unsigned char key[16], size_t len)
+{
+       unsigned char arc4_state[258];
+
+       smb_arc4_init(arc4_state, key, 16);
+       smb_arc4_crypt(arc4_state, data, len);
+}
+
+void SamOEMhashBlob( unsigned char *data, size_t len, DATA_BLOB *key)
+{
+       unsigned char arc4_state[258];
+
+       smb_arc4_init(arc4_state, key->data, key->length);
+       smb_arc4_crypt(arc4_state, data, len);
+}
+
+/* Decode a sam password hash into a password.  The password hash is the
+   same method used to store passwords in the NT registry.  The DES key
+   used is based on the RID of the user. */
+
+void sam_pwd_hash(unsigned int rid, const uchar *in, uchar *out, int forw)
+{
+       uchar s[14];
+
+       s[0] = s[4] = s[8] = s[12] = (uchar)(rid & 0xFF);
+       s[1] = s[5] = s[9] = s[13] = (uchar)((rid >> 8) & 0xFF);
+       s[2] = s[6] = s[10]        = (uchar)((rid >> 16) & 0xFF);
+       s[3] = s[7] = s[11]        = (uchar)((rid >> 24) & 0xFF);
+
+       des_crypt56(out, in, s, forw);
+       des_crypt56(out+8, in+8, s+7, forw);
+}