Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[deliverable/linux.git] / fs / cifs / smbencrypt.c
CommitLineData
790fe579 1/*
1da177e4
LT
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB parameters and setup
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
7 Modified by Jeremy Allison 1995.
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
9 Modified by Steve French (sfrench@us.ibm.com) 2002-2003
50c2f753 10
1da177e4
LT
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.
50c2f753 15
1da177e4
LT
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.
50c2f753 20
1da177e4
LT
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
9651ddba 26#include <crypto/skcipher.h>
1da177e4 27#include <linux/module.h>
5a0e3ad6 28#include <linux/slab.h>
1da177e4
LT
29#include <linux/fs.h>
30#include <linux/string.h>
31#include <linux/kernel.h>
32#include <linux/random.h>
2baa2682 33#include "cifs_fs_sb.h"
1da177e4
LT
34#include "cifs_unicode.h"
35#include "cifspdu.h"
3979877e 36#include "cifsglob.h"
1da177e4 37#include "cifs_debug.h"
ee2c9258 38#include "cifsproto.h"
1da177e4 39
4b18f2a9
SF
40#ifndef false
41#define false 0
1da177e4 42#endif
4b18f2a9
SF
43#ifndef true
44#define true 1
1da177e4
LT
45#endif
46
47/* following came from the other byteorder.h to avoid include conflicts */
48#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
49#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
50#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
51
43988d76
SF
52static void
53str_to_key(unsigned char *str, unsigned char *key)
54{
55 int i;
56
57 key[0] = str[0] >> 1;
58 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
59 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
60 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
61 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
62 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
63 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
64 key[7] = str[6] & 0x7F;
65 for (i = 0; i < 8; i++)
66 key[i] = (key[i] << 1);
67}
68
69static int
70smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
71{
72 int rc;
73 unsigned char key2[8];
9651ddba 74 struct crypto_skcipher *tfm_des;
43988d76 75 struct scatterlist sgin, sgout;
9651ddba 76 struct skcipher_request *req;
43988d76
SF
77
78 str_to_key(key, key2);
79
9651ddba 80 tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
43988d76
SF
81 if (IS_ERR(tfm_des)) {
82 rc = PTR_ERR(tfm_des);
f96637be 83 cifs_dbg(VFS, "could not allocate des crypto API\n");
43988d76
SF
84 goto smbhash_err;
85 }
86
9651ddba
HX
87 req = skcipher_request_alloc(tfm_des, GFP_KERNEL);
88 if (!req) {
89 rc = -ENOMEM;
90 cifs_dbg(VFS, "could not allocate des crypto API\n");
91 goto smbhash_free_skcipher;
92 }
43988d76 93
9651ddba 94 crypto_skcipher_setkey(tfm_des, key2, 8);
43988d76
SF
95
96 sg_init_one(&sgin, in, 8);
97 sg_init_one(&sgout, out, 8);
98
9651ddba
HX
99 skcipher_request_set_callback(req, 0, NULL, NULL);
100 skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL);
101
102 rc = crypto_skcipher_encrypt(req);
e4fb0edb 103 if (rc)
f96637be 104 cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc);
43988d76 105
9651ddba
HX
106 skcipher_request_free(req);
107
108smbhash_free_skcipher:
109 crypto_free_skcipher(tfm_des);
43988d76
SF
110smbhash_err:
111 return rc;
112}
113
114static int
115E_P16(unsigned char *p14, unsigned char *p16)
116{
117 int rc;
118 unsigned char sp8[8] =
119 { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
120
121 rc = smbhash(p16, sp8, p14);
122 if (rc)
123 return rc;
124 rc = smbhash(p16 + 8, sp8, p14 + 7);
125 return rc;
126}
127
128static int
129E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
130{
131 int rc;
132
133 rc = smbhash(p24, c8, p21);
134 if (rc)
135 return rc;
136 rc = smbhash(p24 + 8, c8, p21 + 7);
137 if (rc)
138 return rc;
139 rc = smbhash(p24 + 16, c8, p21 + 14);
140 return rc;
141}
142
ee2c9258
SP
143/* produce a md4 message digest from data of length n bytes */
144int
145mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
146{
147 int rc;
148 unsigned int size;
149 struct crypto_shash *md4;
150 struct sdesc *sdescmd4;
151
152 md4 = crypto_alloc_shash("md4", 0, 0);
153 if (IS_ERR(md4)) {
ffeb414a 154 rc = PTR_ERR(md4);
f96637be
JP
155 cifs_dbg(VFS, "%s: Crypto md4 allocation error %d\n",
156 __func__, rc);
ffeb414a 157 return rc;
ee2c9258
SP
158 }
159 size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
160 sdescmd4 = kmalloc(size, GFP_KERNEL);
161 if (!sdescmd4) {
162 rc = -ENOMEM;
ee2c9258
SP
163 goto mdfour_err;
164 }
165 sdescmd4->shash.tfm = md4;
166 sdescmd4->shash.flags = 0x0;
167
168 rc = crypto_shash_init(&sdescmd4->shash);
169 if (rc) {
f96637be 170 cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
ee2c9258
SP
171 goto mdfour_err;
172 }
14cae324
SP
173 rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
174 if (rc) {
f96637be 175 cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
14cae324
SP
176 goto mdfour_err;
177 }
ee2c9258 178 rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
14cae324 179 if (rc)
f96637be 180 cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
1da177e4 181
ee2c9258
SP
182mdfour_err:
183 crypto_free_shash(md4);
184 kfree(sdescmd4);
185
186 return rc;
187}
188
1da177e4
LT
189/*
190 This implements the X/Open SMB password encryption
790fe579 191 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
1da177e4
LT
192 encrypted password into p24 */
193/* Note that password must be uppercased and null terminated */
43988d76 194int
4e53a3fb 195SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
1da177e4 196{
43988d76
SF
197 int rc;
198 unsigned char p14[14], p16[16], p21[21];
1da177e4 199
1da177e4 200 memset(p14, '\0', 14);
43988d76
SF
201 memset(p16, '\0', 16);
202 memset(p21, '\0', 21);
1da177e4 203
43988d76
SF
204 memcpy(p14, passwd, 14);
205 rc = E_P16(p14, p16);
206 if (rc)
207 return rc;
1da177e4 208
43988d76
SF
209 memcpy(p21, p16, 16);
210 rc = E_P24(p21, c8, p24);
50c2f753 211
43988d76 212 return rc;
1da177e4
LT
213}
214
790fe579 215/*
1da177e4
LT
216 * Creates the MD4 Hash of the users password in NT UNICODE.
217 */
218
ee2c9258 219int
9ef5992e
SP
220E_md4hash(const unsigned char *passwd, unsigned char *p16,
221 const struct nls_table *codepage)
1da177e4 222{
ee2c9258 223 int rc;
1da177e4 224 int len;
9c32c63b 225 __le16 wpwd[129];
1da177e4
LT
226
227 /* Password cannot be longer than 128 characters */
9ef5992e 228 if (passwd) /* Password must be converted to NT unicode */
acbbb76a 229 len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
9ef5992e 230 else {
1da177e4 231 len = 0;
9ef5992e
SP
232 *wpwd = 0; /* Ensure string is null terminated */
233 }
1da177e4 234
9c32c63b 235 rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16));
f99dbfa4 236 memzero_explicit(wpwd, sizeof(wpwd));
ee2c9258
SP
237
238 return rc;
1da177e4
LT
239}
240
1da177e4 241/* Does the NT MD4 hash then des encryption. */
ee2c9258 242int
9ef5992e
SP
243SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
244 const struct nls_table *codepage)
1da177e4 245{
ee2c9258 246 int rc;
43988d76 247 unsigned char p16[16], p21[21];
1da177e4 248
43988d76 249 memset(p16, '\0', 16);
1da177e4
LT
250 memset(p21, '\0', 21);
251
9ef5992e 252 rc = E_md4hash(passwd, p16, codepage);
ee2c9258 253 if (rc) {
f96637be
JP
254 cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
255 __func__, rc);
ee2c9258
SP
256 return rc;
257 }
43988d76
SF
258 memcpy(p21, p16, 16);
259 rc = E_P24(p21, c8, p24);
ee2c9258 260 return rc;
1da177e4 261}
This page took 0.676358 seconds and 5 git commands to generate.