xref: /openbsd-src/sbin/iked/chap_ms.c (revision 08c24fdd6abd7a4c82cb96d2b3e6778a0ffceb07)
1*08c24fddStobhe /*	$OpenBSD: chap_ms.c,v 1.10 2021/02/04 19:59:15 tobhe Exp $	*/
245ae9d61Sreyk 
345ae9d61Sreyk /*
4fcebd35dSreyk  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
545ae9d61Sreyk  * Copyright (c) 1997-2001 Brian Somers <brian@Awfulhak.org>
645ae9d61Sreyk  * Copyright (c) 1997 Gabor Kincses <gabor@acm.org>
745ae9d61Sreyk  * Copyright (c) 1995 Eric Rosenquist
845ae9d61Sreyk  *
945ae9d61Sreyk  * All rights reserved.
1045ae9d61Sreyk  *
1145ae9d61Sreyk  * Redistribution and use in source and binary forms, with or without
1245ae9d61Sreyk  * modification, are permitted provided that the following conditions
1345ae9d61Sreyk  * are met:
1445ae9d61Sreyk  * 1. Redistributions of source code must retain the above copyright
1545ae9d61Sreyk  *    notice, this list of conditions and the following disclaimer.
1645ae9d61Sreyk  * 2. Redistributions in binary form must reproduce the above copyright
1745ae9d61Sreyk  *    notice, this list of conditions and the following disclaimer in the
1845ae9d61Sreyk  *    documentation and/or other materials provided with the distribution.
1945ae9d61Sreyk  *
2045ae9d61Sreyk  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2145ae9d61Sreyk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2245ae9d61Sreyk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2345ae9d61Sreyk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2445ae9d61Sreyk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2545ae9d61Sreyk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2645ae9d61Sreyk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2745ae9d61Sreyk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2845ae9d61Sreyk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2945ae9d61Sreyk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3045ae9d61Sreyk  * SUCH DAMAGE.
3145ae9d61Sreyk   */
3245ae9d61Sreyk 
3345ae9d61Sreyk #include <sys/types.h>
3445ae9d61Sreyk 
3545ae9d61Sreyk #include <ctype.h>
3645ae9d61Sreyk #include <string.h>
3745ae9d61Sreyk #include <stdio.h>
3845ae9d61Sreyk 
3945ae9d61Sreyk #include <openssl/evp.h>
4045ae9d61Sreyk #include <openssl/des.h>
4145ae9d61Sreyk #include <openssl/md4.h>
4245ae9d61Sreyk #include <openssl/md5.h>
4345ae9d61Sreyk #include <openssl/sha.h>
4445ae9d61Sreyk 
4545ae9d61Sreyk #include "chap_ms.h"
4645ae9d61Sreyk 
47*08c24fddStobhe extern __dead void fatalx(const char *, ...)
48*08c24fddStobhe 	    __attribute__((__format__ (printf, 1, 2)));
49*08c24fddStobhe 
5045ae9d61Sreyk /*
5145ae9d61Sreyk  * Documentation & specifications:
5245ae9d61Sreyk  *
5345ae9d61Sreyk  * MS-CHAP (CHAP80)	RFC2433
5445ae9d61Sreyk  * MS-CHAP-V2 (CHAP81)	RFC2759
5545ae9d61Sreyk  * MPPE key management	RFC3079
5645ae9d61Sreyk  *
5745ae9d61Sreyk  * Security analysis:
5845ae9d61Sreyk  * Schneier/Mudge/Wagner, "MS-CHAP-v2", Oct 99
5945ae9d61Sreyk  * "It is unclear to us why this protocol is so complicated."
6045ae9d61Sreyk  */
6145ae9d61Sreyk 
62d09d3a7dSreyk static uint8_t sha1_pad1[40] = {
6345ae9d61Sreyk 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6445ae9d61Sreyk 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6545ae9d61Sreyk 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6645ae9d61Sreyk 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6745ae9d61Sreyk };
6845ae9d61Sreyk 
69d09d3a7dSreyk static uint8_t sha1_pad2[40] = {
7045ae9d61Sreyk 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
7145ae9d61Sreyk 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
7245ae9d61Sreyk 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
7345ae9d61Sreyk 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
7445ae9d61Sreyk };
7545ae9d61Sreyk 
76d09d3a7dSreyk uint8_t		 get7bits(uint8_t *, int);
77d09d3a7dSreyk void		 mschap_des_addparity(uint8_t *, uint8_t *);
78d09d3a7dSreyk void		 mschap_des_encrypt(uint8_t *, uint8_t *, uint8_t *);
79d09d3a7dSreyk void		 mschap_challenge_response(uint8_t *, uint8_t *, uint8_t *);
8045ae9d61Sreyk 
81d09d3a7dSreyk uint8_t
get7bits(uint8_t * in,int start)82d09d3a7dSreyk get7bits(uint8_t *in, int start)
8345ae9d61Sreyk {
84d09d3a7dSreyk 	unsigned int	 word;
8545ae9d61Sreyk 
86d09d3a7dSreyk 	word = (unsigned int)in[start / 8] << 8;
87d09d3a7dSreyk 	word |= (unsigned int)in[start / 8 + 1];
8845ae9d61Sreyk 	word >>= 15 - (start % 8 + 7);
8945ae9d61Sreyk 
9045ae9d61Sreyk 	return (word & 0xfe);
9145ae9d61Sreyk }
9245ae9d61Sreyk 
9345ae9d61Sreyk /* IN  56 bit DES key missing parity bits
9445ae9d61Sreyk    OUT 64 bit DES key with parity bits added */
9545ae9d61Sreyk void
mschap_des_addparity(uint8_t * key,uint8_t * des_key)96d09d3a7dSreyk mschap_des_addparity(uint8_t *key, uint8_t *des_key)
9745ae9d61Sreyk {
9845ae9d61Sreyk 	des_key[0] = get7bits(key,  0);
9945ae9d61Sreyk 	des_key[1] = get7bits(key,  7);
10045ae9d61Sreyk 	des_key[2] = get7bits(key, 14);
10145ae9d61Sreyk 	des_key[3] = get7bits(key, 21);
10245ae9d61Sreyk 	des_key[4] = get7bits(key, 28);
10345ae9d61Sreyk 	des_key[5] = get7bits(key, 35);
10445ae9d61Sreyk 	des_key[6] = get7bits(key, 42);
10545ae9d61Sreyk 	des_key[7] = get7bits(key, 49);
10645ae9d61Sreyk 
1070f795b9cSmiod 	DES_set_odd_parity((DES_cblock *)des_key);
10845ae9d61Sreyk }
10945ae9d61Sreyk 
11045ae9d61Sreyk void
mschap_des_encrypt(uint8_t * clear,uint8_t * key,uint8_t * cipher)111d09d3a7dSreyk mschap_des_encrypt(uint8_t *clear, uint8_t *key, uint8_t *cipher)
11245ae9d61Sreyk {
1130f795b9cSmiod 	DES_cblock		des_key;
1140f795b9cSmiod 	DES_key_schedule	key_schedule;
11545ae9d61Sreyk 
11645ae9d61Sreyk 	mschap_des_addparity(key, des_key);
11745ae9d61Sreyk 
11845ae9d61Sreyk 	DES_set_key(&des_key, &key_schedule);
1190f795b9cSmiod 	DES_ecb_encrypt((DES_cblock *)clear, (DES_cblock *)cipher,
12045ae9d61Sreyk 	    &key_schedule, 1);
12145ae9d61Sreyk }
12245ae9d61Sreyk 
12345ae9d61Sreyk void
mschap_challenge_response(uint8_t * challenge,uint8_t * pwhash,uint8_t * response)124d09d3a7dSreyk mschap_challenge_response(uint8_t *challenge, uint8_t *pwhash,
125d09d3a7dSreyk     uint8_t *response)
12645ae9d61Sreyk {
127d09d3a7dSreyk 	uint8_t		 padpwhash[21 + 1];
12845ae9d61Sreyk 
12945ae9d61Sreyk 	bzero(&padpwhash, sizeof(padpwhash));
13045ae9d61Sreyk 	memcpy(padpwhash, pwhash, MSCHAP_HASH_SZ);
13145ae9d61Sreyk 
13245ae9d61Sreyk 	mschap_des_encrypt(challenge, padpwhash + 0, response + 0);
13345ae9d61Sreyk 	mschap_des_encrypt(challenge, padpwhash + 7, response + 8);
13445ae9d61Sreyk 	mschap_des_encrypt(challenge, padpwhash + 14, response + 16);
13545ae9d61Sreyk }
13645ae9d61Sreyk 
13745ae9d61Sreyk void
mschap_ntpassword_hash(uint8_t * in,int inlen,uint8_t * hash)138d09d3a7dSreyk mschap_ntpassword_hash(uint8_t *in, int inlen, uint8_t *hash)
13945ae9d61Sreyk {
140*08c24fddStobhe 	EVP_MD_CTX	 *ctx;
141d09d3a7dSreyk 	unsigned int	 mdlen;
14245ae9d61Sreyk 
143*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
144*08c24fddStobhe 	if (ctx == NULL)
145*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
146*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_md4());
147*08c24fddStobhe 	EVP_DigestUpdate(ctx, in, inlen);
148*08c24fddStobhe 	EVP_DigestFinal(ctx, hash, &mdlen);
149*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
15045ae9d61Sreyk }
15145ae9d61Sreyk 
15245ae9d61Sreyk void
mschap_challenge_hash(uint8_t * peer_challenge,uint8_t * auth_challenge,uint8_t * username,int usernamelen,uint8_t * challenge)153d09d3a7dSreyk mschap_challenge_hash(uint8_t *peer_challenge, uint8_t *auth_challenge,
154d09d3a7dSreyk     uint8_t *username, int usernamelen, uint8_t *challenge)
15545ae9d61Sreyk {
156*08c24fddStobhe 	EVP_MD_CTX	*ctx;
157d09d3a7dSreyk 	uint8_t		 md[SHA_DIGEST_LENGTH];
158d09d3a7dSreyk 	unsigned int	 mdlen;
159d09d3a7dSreyk 	uint8_t		*name;
16045ae9d61Sreyk 
16145ae9d61Sreyk 	if ((name = strrchr(username, '\\')) == NULL)
16245ae9d61Sreyk 		name = username;
16345ae9d61Sreyk 	else
16445ae9d61Sreyk 		name++;
16545ae9d61Sreyk 
166*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
167*08c24fddStobhe 	if (ctx == NULL)
168*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
169*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_sha1());
170*08c24fddStobhe 	EVP_DigestUpdate(ctx, peer_challenge, MSCHAPV2_CHALLENGE_SZ);
171*08c24fddStobhe 	EVP_DigestUpdate(ctx, auth_challenge, MSCHAPV2_CHALLENGE_SZ);
172*08c24fddStobhe 	EVP_DigestUpdate(ctx, name, strlen(name));
173*08c24fddStobhe 	EVP_DigestFinal(ctx, md, &mdlen);
174*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
17545ae9d61Sreyk 
17645ae9d61Sreyk 	memcpy(challenge, md, MSCHAP_CHALLENGE_SZ);
17745ae9d61Sreyk }
17845ae9d61Sreyk 
17945ae9d61Sreyk void
mschap_nt_response(uint8_t * auth_challenge,uint8_t * peer_challenge,uint8_t * username,int usernamelen,uint8_t * password,int passwordlen,uint8_t * response)180d09d3a7dSreyk mschap_nt_response(uint8_t *auth_challenge, uint8_t *peer_challenge,
181d09d3a7dSreyk     uint8_t *username, int usernamelen, uint8_t *password, int passwordlen,
182d09d3a7dSreyk     uint8_t *response)
18345ae9d61Sreyk {
184d09d3a7dSreyk 	uint8_t		 challenge[MSCHAP_CHALLENGE_SZ];
185d09d3a7dSreyk 	uint8_t		 password_hash[MSCHAP_HASH_SZ];
18645ae9d61Sreyk 
18745ae9d61Sreyk 	mschap_challenge_hash(peer_challenge, auth_challenge,
18845ae9d61Sreyk 	    username, usernamelen, challenge);
18945ae9d61Sreyk 
19045ae9d61Sreyk 	mschap_ntpassword_hash(password, passwordlen, password_hash);
19145ae9d61Sreyk 	mschap_challenge_response(challenge, password_hash, response);
19245ae9d61Sreyk }
19345ae9d61Sreyk 
19445ae9d61Sreyk void
mschap_auth_response(uint8_t * password,int passwordlen,uint8_t * ntresponse,uint8_t * auth_challenge,uint8_t * peer_challenge,uint8_t * username,int usernamelen,uint8_t * auth_response)195d09d3a7dSreyk mschap_auth_response(uint8_t *password, int passwordlen,
196d09d3a7dSreyk     uint8_t *ntresponse, uint8_t *auth_challenge, uint8_t *peer_challenge,
197d09d3a7dSreyk     uint8_t *username, int usernamelen, uint8_t *auth_response)
19845ae9d61Sreyk {
199*08c24fddStobhe 	EVP_MD_CTX	*ctx;
200d09d3a7dSreyk 	uint8_t		 password_hash[MSCHAP_HASH_SZ];
201d09d3a7dSreyk 	uint8_t		 password_hash2[MSCHAP_HASH_SZ];
202d09d3a7dSreyk 	uint8_t		 challenge[MSCHAP_CHALLENGE_SZ];
203d09d3a7dSreyk 	uint8_t		 md[SHA_DIGEST_LENGTH], *ptr;
204d09d3a7dSreyk 	unsigned int	 mdlen;
20545ae9d61Sreyk 	int		 i;
206d09d3a7dSreyk 	const uint8_t	 hex[] = "0123456789ABCDEF";
207d09d3a7dSreyk 	static uint8_t	 magic1[39] = {
20845ae9d61Sreyk 		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
20945ae9d61Sreyk 		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
21045ae9d61Sreyk 		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
21145ae9d61Sreyk 		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
21245ae9d61Sreyk 	};
213d09d3a7dSreyk 	static uint8_t	 magic2[41] = {
21445ae9d61Sreyk 		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
21545ae9d61Sreyk 		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
21645ae9d61Sreyk 		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
21745ae9d61Sreyk 		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
21845ae9d61Sreyk 		0x6E
21945ae9d61Sreyk 	};
22045ae9d61Sreyk 
221*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
222*08c24fddStobhe 	if (ctx == NULL)
223*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
22445ae9d61Sreyk 	mschap_ntpassword_hash(password, passwordlen, password_hash);
22545ae9d61Sreyk 	mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
22645ae9d61Sreyk 
227*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_sha1());
228*08c24fddStobhe 	EVP_DigestUpdate(ctx, password_hash2, sizeof(password_hash2));
229*08c24fddStobhe 	EVP_DigestUpdate(ctx, ntresponse, 24);
230*08c24fddStobhe 	EVP_DigestUpdate(ctx, magic1, 39);
231*08c24fddStobhe 	EVP_DigestFinal(ctx, md, &mdlen);
23245ae9d61Sreyk 
23345ae9d61Sreyk 	mschap_challenge_hash(peer_challenge, auth_challenge,
23445ae9d61Sreyk 	    username, usernamelen, challenge);
23545ae9d61Sreyk 
236*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_sha1());
237*08c24fddStobhe 	EVP_DigestUpdate(ctx, md, sizeof(md));
238*08c24fddStobhe 	EVP_DigestUpdate(ctx, challenge, sizeof(challenge));
239*08c24fddStobhe 	EVP_DigestUpdate(ctx, magic2, 41);
240*08c24fddStobhe 	EVP_DigestFinal(ctx, md, &mdlen);
241*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
24245ae9d61Sreyk 
24345ae9d61Sreyk 	/*
24445ae9d61Sreyk 	 * Encode the value of 'Digest' as "S=" followed by
24545ae9d61Sreyk 	 * 40 ASCII hexadecimal digits and return it in
24645ae9d61Sreyk 	 * AuthenticatorResponse.
24745ae9d61Sreyk 	 * For example,
24845ae9d61Sreyk 	 *   "S=0123456789ABCDEF0123456789ABCDEF01234567"
24945ae9d61Sreyk 	 */
25045ae9d61Sreyk 	ptr = auth_response;
25145ae9d61Sreyk 	*ptr++ = 'S';
25245ae9d61Sreyk 	*ptr++ = '=';
25345ae9d61Sreyk 	for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
25445ae9d61Sreyk 		*ptr++ = hex[md[i] >> 4];
25545ae9d61Sreyk 		*ptr++ = hex[md[i] & 0x0f];
25645ae9d61Sreyk 	}
25745ae9d61Sreyk }
25845ae9d61Sreyk 
25945ae9d61Sreyk void
mschap_masterkey(uint8_t * password_hash2,uint8_t * ntresponse,uint8_t * masterkey)260d09d3a7dSreyk mschap_masterkey(uint8_t *password_hash2, uint8_t *ntresponse,
261d09d3a7dSreyk     uint8_t *masterkey)
26245ae9d61Sreyk {
263d09d3a7dSreyk 	uint8_t		 md[SHA_DIGEST_LENGTH];
264d09d3a7dSreyk 	unsigned int	 mdlen;
265*08c24fddStobhe 	EVP_MD_CTX	*ctx;
266d09d3a7dSreyk 	static uint8_t	 magic1[27] = {
26745ae9d61Sreyk 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
26845ae9d61Sreyk 		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
26945ae9d61Sreyk 		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
27045ae9d61Sreyk 	};
27145ae9d61Sreyk 
272*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
273*08c24fddStobhe 	if (ctx == NULL)
274*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
275*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_sha1());
276*08c24fddStobhe 	EVP_DigestUpdate(ctx, password_hash2, MSCHAP_HASH_SZ);
277*08c24fddStobhe 	EVP_DigestUpdate(ctx, ntresponse, 24);
278*08c24fddStobhe 	EVP_DigestUpdate(ctx, magic1, 27);
279*08c24fddStobhe 	EVP_DigestFinal(ctx, md, &mdlen);
280*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
28145ae9d61Sreyk 
28245ae9d61Sreyk 	memcpy(masterkey, md, 16);
28345ae9d61Sreyk }
28445ae9d61Sreyk 
28545ae9d61Sreyk void
mschap_asymetric_startkey(uint8_t * masterkey,uint8_t * sessionkey,int sessionkeylen,int issend,int isserver)286d09d3a7dSreyk mschap_asymetric_startkey(uint8_t *masterkey, uint8_t *sessionkey,
28745ae9d61Sreyk     int sessionkeylen, int issend, int isserver)
28845ae9d61Sreyk {
289*08c24fddStobhe 	EVP_MD_CTX	*ctx;
290d09d3a7dSreyk 	uint8_t		 md[SHA_DIGEST_LENGTH];
291d09d3a7dSreyk 	unsigned int	 mdlen;
292d09d3a7dSreyk 	uint8_t		*s;
293d09d3a7dSreyk 	static uint8_t	 magic2[84] = {
29445ae9d61Sreyk 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
29545ae9d61Sreyk 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
29645ae9d61Sreyk 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
29745ae9d61Sreyk 		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
29845ae9d61Sreyk 		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
29945ae9d61Sreyk 		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
30045ae9d61Sreyk 		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
30145ae9d61Sreyk 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
30245ae9d61Sreyk 		0x6b, 0x65, 0x79, 0x2e
30345ae9d61Sreyk 	};
304d09d3a7dSreyk 	static uint8_t	 magic3[84] = {
30545ae9d61Sreyk 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
30645ae9d61Sreyk 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
30745ae9d61Sreyk 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
30845ae9d61Sreyk 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
30945ae9d61Sreyk 		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
31045ae9d61Sreyk 		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
31145ae9d61Sreyk 		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
31245ae9d61Sreyk 		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
31345ae9d61Sreyk 		0x6b, 0x65, 0x79, 0x2e
31445ae9d61Sreyk 	};
31545ae9d61Sreyk 
31645ae9d61Sreyk 	if (issend)
31745ae9d61Sreyk 		s = isserver ? magic3 : magic2;
31845ae9d61Sreyk 	else
31945ae9d61Sreyk 		s = isserver ? magic2 : magic3;
32045ae9d61Sreyk 
321*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
322*08c24fddStobhe 	if (ctx == NULL)
323*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
324*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_sha1());
325*08c24fddStobhe 	EVP_DigestUpdate(ctx, masterkey, 16);
326*08c24fddStobhe 	EVP_DigestUpdate(ctx, sha1_pad1, 40);
327*08c24fddStobhe 	EVP_DigestUpdate(ctx, s, 84);
328*08c24fddStobhe 	EVP_DigestUpdate(ctx, sha1_pad2, 40);
329*08c24fddStobhe 	EVP_DigestFinal(ctx, md, &mdlen);
330*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
33145ae9d61Sreyk 
33245ae9d61Sreyk 	memcpy(sessionkey, md, sessionkeylen);
33345ae9d61Sreyk }
33445ae9d61Sreyk 
33545ae9d61Sreyk void
mschap_msk(uint8_t * password,int passwordlen,uint8_t * ntresponse,uint8_t * msk)336d09d3a7dSreyk mschap_msk(uint8_t *password, int passwordlen,
337d09d3a7dSreyk     uint8_t *ntresponse, uint8_t *msk)
33845ae9d61Sreyk {
339d09d3a7dSreyk 	uint8_t		 password_hash[MSCHAP_HASH_SZ];
340d09d3a7dSreyk 	uint8_t		 password_hash2[MSCHAP_HASH_SZ];
341d09d3a7dSreyk 	uint8_t		 masterkey[MSCHAP_MASTERKEY_SZ];
342d09d3a7dSreyk 	uint8_t		 sendkey[MSCHAP_MASTERKEY_SZ];
343d09d3a7dSreyk 	uint8_t		 recvkey[MSCHAP_MASTERKEY_SZ];
34445ae9d61Sreyk 
34545ae9d61Sreyk 	mschap_ntpassword_hash(password, passwordlen, password_hash);
34645ae9d61Sreyk 	mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
34745ae9d61Sreyk 
34845ae9d61Sreyk 	mschap_masterkey(password_hash2, ntresponse, masterkey);
34945ae9d61Sreyk 	mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1);
35045ae9d61Sreyk 	mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1);
35145ae9d61Sreyk 
35245ae9d61Sreyk 	/* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */
35345ae9d61Sreyk 	bzero(msk, MSCHAP_MSK_SZ);
35445ae9d61Sreyk 	memcpy(msk, &recvkey, sizeof(recvkey));
35545ae9d61Sreyk 	memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey));
35645ae9d61Sreyk }
35745ae9d61Sreyk 
35845ae9d61Sreyk void
mschap_radiuskey(uint8_t * plain,const uint8_t * crypted,const uint8_t * authenticator,const uint8_t * secret)359d09d3a7dSreyk mschap_radiuskey(uint8_t *plain, const uint8_t *crypted,
360d09d3a7dSreyk     const uint8_t *authenticator, const uint8_t *secret)
36145ae9d61Sreyk {
362*08c24fddStobhe 	EVP_MD_CTX	*ctx;
363d09d3a7dSreyk 	uint8_t		 b[MD5_DIGEST_LENGTH], p[32];
364d09d3a7dSreyk 	unsigned int	 i, mdlen;
36545ae9d61Sreyk 
366*08c24fddStobhe 	ctx = EVP_MD_CTX_new();
367*08c24fddStobhe 	if (ctx == NULL)
368*08c24fddStobhe 		fatalx("%s: EVP_MD_CTX_NEW()", __func__);
369*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_md5());
370*08c24fddStobhe 	EVP_DigestUpdate(ctx, secret, strlen(secret));
371*08c24fddStobhe 	EVP_DigestUpdate(ctx, authenticator, 16);
372*08c24fddStobhe 	EVP_DigestUpdate(ctx, crypted, 2);
373*08c24fddStobhe 	EVP_DigestFinal(ctx, b, &mdlen);
37445ae9d61Sreyk 
37545ae9d61Sreyk 	for (i = 0; i < mdlen; i++) {
37645ae9d61Sreyk 		p[i] = b[i] ^ crypted[i+2];
37745ae9d61Sreyk 	}
37845ae9d61Sreyk 
379*08c24fddStobhe 	EVP_DigestInit(ctx, EVP_md5());
380*08c24fddStobhe 	EVP_DigestUpdate(ctx, secret, strlen(secret));
381*08c24fddStobhe 	EVP_DigestUpdate(ctx, crypted + 2, mdlen);
382*08c24fddStobhe 	EVP_DigestFinal(ctx, b, &mdlen);
383*08c24fddStobhe 	EVP_MD_CTX_free(ctx);
38445ae9d61Sreyk 
38545ae9d61Sreyk 	for (i = 0; i < mdlen; i++) {
38645ae9d61Sreyk 		p[i+16] = b[i] ^ crypted[i+18];
38745ae9d61Sreyk 	}
38845ae9d61Sreyk 
38945ae9d61Sreyk 	memcpy(plain, p+1, 16);
39045ae9d61Sreyk }
391