xref: /openbsd-src/sbin/iked/chap_ms.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: chap_ms.c,v 1.2 2011/05/27 12:01:02 reyk Exp $	*/
2 /*	$vantronix: chap_ms.c,v 1.7 2010/06/02 12:22:58 reyk Exp $	*/
3 
4 /*
5  * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
6  * Copyright (c) 1997 - 2001 Brian Somers <brian@Awfulhak.org>
7  * Copyright (c) 1997 Gabor Kincses <gabor@acm.org>
8  * Copyright (c) 1995 Eric Rosenquist
9  *
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32   */
33 
34 #include <sys/types.h>
35 #include <sys/cdefs.h>
36 
37 #include <ctype.h>
38 #include <string.h>
39 #include <stdio.h>
40 
41 #include <openssl/evp.h>
42 #include <openssl/des.h>
43 #include <openssl/md4.h>
44 #include <openssl/md5.h>
45 #include <openssl/sha.h>
46 
47 #include "chap_ms.h"
48 
49 /*
50  * Documentation & specifications:
51  *
52  * MS-CHAP (CHAP80)	RFC2433
53  * MS-CHAP-V2 (CHAP81)	RFC2759
54  * MPPE key management	RFC3079
55  *
56  * Security analysis:
57  * Schneier/Mudge/Wagner, "MS-CHAP-v2", Oct 99
58  * "It is unclear to us why this protocol is so complicated."
59  */
60 
61 static u_int8_t sha1_pad1[40] = {
62 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
66 };
67 
68 static u_int8_t sha1_pad2[40] = {
69 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
70 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
71 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
72 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
73 };
74 
75 u_int8_t	 get7bits(u_int8_t *, int);
76 void		 mschap_des_addparity(u_int8_t *, u_int8_t *);
77 void		 mschap_des_encrypt(u_int8_t *, u_int8_t *, u_int8_t *);
78 void		 mschap_challenge_response(u_int8_t *, u_int8_t *, u_int8_t *);
79 
80 u_int8_t
81 get7bits(u_int8_t *in, int start)
82 {
83 	u_int	 word;
84 
85 	word = (u_int)in[start / 8] << 8;
86 	word |= (u_int)in[start / 8 + 1];
87 	word >>= 15 - (start % 8 + 7);
88 
89 	return (word & 0xfe);
90 }
91 
92 /* IN  56 bit DES key missing parity bits
93    OUT 64 bit DES key with parity bits added */
94 void
95 mschap_des_addparity(u_int8_t *key, u_int8_t *des_key)
96 {
97 	des_key[0] = get7bits(key,  0);
98 	des_key[1] = get7bits(key,  7);
99 	des_key[2] = get7bits(key, 14);
100 	des_key[3] = get7bits(key, 21);
101 	des_key[4] = get7bits(key, 28);
102 	des_key[5] = get7bits(key, 35);
103 	des_key[6] = get7bits(key, 42);
104 	des_key[7] = get7bits(key, 49);
105 
106 	DES_set_odd_parity((des_cblock *)des_key);
107 }
108 
109 void
110 mschap_des_encrypt(u_int8_t *clear, u_int8_t *key, u_int8_t *cipher)
111 {
112 	des_cblock		des_key;
113 	des_key_schedule	key_schedule;
114 
115 	mschap_des_addparity(key, des_key);
116 
117 	DES_set_key(&des_key, &key_schedule);
118 	DES_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher,
119 	    &key_schedule, 1);
120 }
121 
122 void
123 mschap_challenge_response(u_int8_t *challenge, u_int8_t *pwhash,
124     u_int8_t *response)
125 {
126 	u_int8_t	 padpwhash[21];
127 
128 	bzero(&padpwhash, sizeof(padpwhash));
129 	memcpy(padpwhash, pwhash, MSCHAP_HASH_SZ);
130 
131 	mschap_des_encrypt(challenge, padpwhash + 0, response + 0);
132 	mschap_des_encrypt(challenge, padpwhash + 7, response + 8);
133 	mschap_des_encrypt(challenge, padpwhash + 14, response + 16);
134 }
135 
136 void
137 mschap_ntpassword_hash(u_int8_t *in, int inlen, u_int8_t *hash)
138 {
139 	EVP_MD_CTX	 ctx;
140 	u_int		 mdlen;
141 
142 	EVP_DigestInit(&ctx, EVP_md4());
143 	EVP_DigestUpdate(&ctx, in, inlen);
144 	EVP_DigestFinal(&ctx, hash, &mdlen);
145 }
146 
147 void
148 mschap_challenge_hash(u_int8_t *peer_challenge, u_int8_t *auth_challenge,
149     u_int8_t *username, int usernamelen, u_int8_t *challenge)
150 {
151 	EVP_MD_CTX	 ctx;
152 	u_int8_t	 md[SHA_DIGEST_LENGTH];
153 	u_int		 mdlen;
154 	u_int8_t	*name;
155 
156 	if ((name = strrchr(username, '\\')) == NULL)
157 		name = username;
158 	else
159 		name++;
160 
161 	EVP_DigestInit(&ctx, EVP_sha1());
162 	EVP_DigestUpdate(&ctx, peer_challenge, MSCHAPV2_CHALLENGE_SZ);
163 	EVP_DigestUpdate(&ctx, auth_challenge, MSCHAPV2_CHALLENGE_SZ);
164 	EVP_DigestUpdate(&ctx, name, strlen(name));
165 	EVP_DigestFinal(&ctx, md, &mdlen);
166 
167 	memcpy(challenge, md, MSCHAP_CHALLENGE_SZ);
168 }
169 
170 void
171 mschap_nt_response(u_int8_t *auth_challenge, u_int8_t *peer_challenge,
172     u_int8_t *username, int usernamelen, u_int8_t *password, int passwordlen,
173     u_int8_t *response)
174 {
175 	u_int8_t challenge[MSCHAP_CHALLENGE_SZ];
176 	u_int8_t password_hash[MSCHAP_HASH_SZ];
177 
178 	mschap_challenge_hash(peer_challenge, auth_challenge,
179 	    username, usernamelen, challenge);
180 
181 	mschap_ntpassword_hash(password, passwordlen, password_hash);
182 	mschap_challenge_response(challenge, password_hash, response);
183 }
184 
185 void
186 mschap_auth_response(u_int8_t *password, int passwordlen,
187     u_int8_t *ntresponse, u_int8_t *auth_challenge, u_int8_t *peer_challenge,
188     u_int8_t *username, int usernamelen, u_int8_t *auth_response)
189 {
190 	EVP_MD_CTX	 ctx;
191 	u_int8_t	 password_hash[MSCHAP_HASH_SZ];
192 	u_int8_t	 password_hash2[MSCHAP_HASH_SZ];
193 	u_int8_t	 challenge[MSCHAP_CHALLENGE_SZ];
194 	u_int8_t	 md[SHA_DIGEST_LENGTH], *ptr;
195 	u_int		 mdlen;
196 	int		 i;
197 	const u_int8_t	 hex[] = "0123456789ABCDEF";
198 	static u_int8_t	 magic1[39] = {
199 		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
200 		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
201 		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
202 		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
203 	};
204 	static u_int8_t	 magic2[41] = {
205 		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
206 		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
207 		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
208 		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
209 		0x6E
210 	};
211 
212 	mschap_ntpassword_hash(password, passwordlen, password_hash);
213 	mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
214 
215 	EVP_DigestInit(&ctx, EVP_sha1());
216 	EVP_DigestUpdate(&ctx, password_hash2, sizeof(password_hash2));
217 	EVP_DigestUpdate(&ctx, ntresponse, 24);
218 	EVP_DigestUpdate(&ctx, magic1, 39);
219 	EVP_DigestFinal(&ctx, md, &mdlen);
220 
221 	mschap_challenge_hash(peer_challenge, auth_challenge,
222 	    username, usernamelen, challenge);
223 
224 	EVP_DigestInit(&ctx, EVP_sha1());
225 	EVP_DigestUpdate(&ctx, md, sizeof(md));
226 	EVP_DigestUpdate(&ctx, challenge, sizeof(challenge));
227 	EVP_DigestUpdate(&ctx, magic2, 41);
228 	EVP_DigestFinal(&ctx, md, &mdlen);
229 
230 	/*
231 	 * Encode the value of 'Digest' as "S=" followed by
232 	 * 40 ASCII hexadecimal digits and return it in
233 	 * AuthenticatorResponse.
234 	 * For example,
235 	 *   "S=0123456789ABCDEF0123456789ABCDEF01234567"
236 	 */
237 	ptr = auth_response;
238 	*ptr++ = 'S';
239 	*ptr++ = '=';
240 	for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
241 		*ptr++ = hex[md[i] >> 4];
242 		*ptr++ = hex[md[i] & 0x0f];
243 	}
244 }
245 
246 void
247 mschap_masterkey(u_int8_t *password_hash2, u_int8_t *ntresponse,
248     u_int8_t *masterkey)
249 {
250 	u_int8_t	 md[SHA_DIGEST_LENGTH];
251 	u_int		 mdlen;
252 	EVP_MD_CTX	 ctx;
253 	static u_int8_t	 magic1[27] = {
254 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
255 		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
256 		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
257 	};
258 
259 	EVP_DigestInit(&ctx, EVP_sha1());
260 	EVP_DigestUpdate(&ctx, password_hash2, MSCHAP_HASH_SZ);
261 	EVP_DigestUpdate(&ctx, ntresponse, 24);
262 	EVP_DigestUpdate(&ctx, magic1, 27);
263 	EVP_DigestFinal(&ctx, md, &mdlen);
264 
265 	memcpy(masterkey, md, 16);
266 }
267 
268 void
269 mschap_asymetric_startkey(u_int8_t *masterkey, u_int8_t *sessionkey,
270     int sessionkeylen, int issend, int isserver)
271 {
272 	EVP_MD_CTX	 ctx;
273 	u_int8_t	 md[SHA_DIGEST_LENGTH];
274 	u_int		 mdlen;
275 	u_int8_t	*s;
276 	static u_int8_t	 magic2[84] = {
277 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
278 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
279 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
280 		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
281 		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
282 		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
283 		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
284 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
285 		0x6b, 0x65, 0x79, 0x2e
286 	};
287 	static u_int8_t	 magic3[84] = {
288 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
289 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
290 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
291 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
292 		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
293 		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
294 		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
295 		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
296 		0x6b, 0x65, 0x79, 0x2e
297 	};
298 
299 	if (issend)
300 		s = isserver ? magic3 : magic2;
301 	else
302 		s = isserver ? magic2 : magic3;
303 
304 	EVP_DigestInit(&ctx, EVP_sha1());
305 	EVP_DigestUpdate(&ctx, masterkey, 16);
306 	EVP_DigestUpdate(&ctx, sha1_pad1, 40);
307 	EVP_DigestUpdate(&ctx, s, 84);
308 	EVP_DigestUpdate(&ctx, sha1_pad2, 40);
309 	EVP_DigestFinal(&ctx, md, &mdlen);
310 
311 	memcpy(sessionkey, md, sessionkeylen);
312 }
313 
314 void
315 mschap_msk(u_int8_t *password, int passwordlen,
316     u_int8_t *ntresponse, u_int8_t *msk)
317 {
318 	u_int8_t	 password_hash[MSCHAP_HASH_SZ];
319 	u_int8_t	 password_hash2[MSCHAP_HASH_SZ];
320 	u_int8_t	 masterkey[MSCHAP_MASTERKEY_SZ];
321 	u_int8_t	 sendkey[MSCHAP_MASTERKEY_SZ];
322 	u_int8_t	 recvkey[MSCHAP_MASTERKEY_SZ];
323 
324 	mschap_ntpassword_hash(password, passwordlen, password_hash);
325 	mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
326 
327 	mschap_masterkey(password_hash2, ntresponse, masterkey);
328 	mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1);
329 	mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1);
330 
331 	/* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */
332 	bzero(msk, MSCHAP_MSK_SZ);
333 	memcpy(msk, &recvkey, sizeof(recvkey));
334 	memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey));
335 }
336 
337 void
338 mschap_newkey(u_int8_t *startkey, u_int8_t *sessionkey,
339     long sessionkeylen, u_int8_t *key)
340 {
341 	EVP_MD_CTX	 ctx;
342 	u_int8_t	 md[SHA_DIGEST_LENGTH];
343 	u_int		 mdlen;
344 
345 	EVP_DigestInit(&ctx, EVP_sha1());
346 	EVP_DigestUpdate(&ctx, startkey, sessionkeylen);
347 	EVP_DigestUpdate(&ctx, sha1_pad1, sizeof(sha1_pad1));
348 	EVP_DigestUpdate(&ctx, sessionkey, sessionkeylen);
349 	EVP_DigestUpdate(&ctx, sha1_pad2, sizeof(sha1_pad2));
350 	EVP_DigestFinal(&ctx, md, &mdlen);
351 
352 	memcpy(key, md, sessionkeylen);
353 }
354 
355 void
356 mschap_nt(u_int8_t *password_hash, u_int8_t *challenge)
357 {
358 	u_int8_t	 response[24];
359 
360 	mschap_challenge_response(challenge, password_hash, response);
361 	memcpy(password_hash, response, sizeof(response));
362 	password_hash[24] = 1;	/* NT-style response */
363 }
364 
365 void
366 mschap_lanman(u_int8_t *digest, u_int8_t *challenge, u_int8_t *secret)
367 {
368 	static u_int8_t	 salt[] = "KGS!@#$%"; /* RASAPI32.dll */
369 	u_int8_t	 SECRET[14], *ptr, *end;
370 	u_int8_t	 hash[MSCHAP_HASH_SZ];
371 
372 	end = SECRET + sizeof(SECRET);
373 	for (ptr = SECRET; *secret && ptr < end; ptr++, secret++)
374 		*ptr = toupper(*secret);
375 	if (ptr < end)
376 		memset(ptr, '\0', end - ptr);
377 
378 	mschap_des_encrypt(salt, SECRET, hash);
379 	mschap_des_encrypt(salt, SECRET + 7, hash + 8);
380 
381 	mschap_challenge_response(challenge, hash, digest);
382 }
383 
384 void
385 mschap_radiuskey(u_int8_t *plain, const u_int8_t *crypted,
386     const u_int8_t *authenticator, const u_int8_t *secret)
387 {
388 	EVP_MD_CTX	 ctx;
389 	u_int8_t	 b[MD5_DIGEST_LENGTH], p[32];
390 	u_int		 i, mdlen;
391 
392 	EVP_DigestInit(&ctx, EVP_md5());
393 	EVP_DigestUpdate(&ctx, secret, strlen(secret));
394 	EVP_DigestUpdate(&ctx, authenticator, 16);
395 	EVP_DigestUpdate(&ctx, crypted, 2);
396 	EVP_DigestFinal(&ctx, b, &mdlen);
397 
398 	for (i = 0; i < mdlen; i++) {
399 		p[i] = b[i] ^ crypted[i+2];
400 	}
401 
402 	EVP_DigestInit(&ctx, EVP_md5());
403 	EVP_DigestUpdate(&ctx, secret, strlen(secret));
404 	EVP_DigestUpdate(&ctx, crypted + 2, mdlen);
405 	EVP_DigestFinal(&ctx, b, &mdlen);
406 
407 	for (i = 0; i < mdlen; i++) {
408 		p[i+16] = b[i] ^ crypted[i+18];
409 	}
410 
411 	memcpy(plain, p+1, 16);
412 }
413