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