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