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