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