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