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