xref: /dflybsd-src/contrib/wpa_supplicant/src/eap_peer/mschapv2.c (revision 6d49e1aea1f916afb9e202b8d2ad09cfab6e48c3)
1*6d49e1aeSJan Lentfer /*
2*6d49e1aeSJan Lentfer  * MSCHAPV2 (RFC 2759)
3*6d49e1aeSJan Lentfer  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4*6d49e1aeSJan Lentfer  *
5*6d49e1aeSJan Lentfer  * This program is free software; you can redistribute it and/or modify
6*6d49e1aeSJan Lentfer  * it under the terms of the GNU General Public License version 2 as
7*6d49e1aeSJan Lentfer  * published by the Free Software Foundation.
8*6d49e1aeSJan Lentfer  *
9*6d49e1aeSJan Lentfer  * Alternatively, this software may be distributed under the terms of BSD
10*6d49e1aeSJan Lentfer  * license.
11*6d49e1aeSJan Lentfer  *
12*6d49e1aeSJan Lentfer  * See README and COPYING for more details.
13*6d49e1aeSJan Lentfer  */
14*6d49e1aeSJan Lentfer 
15*6d49e1aeSJan Lentfer #include "includes.h"
16*6d49e1aeSJan Lentfer 
17*6d49e1aeSJan Lentfer #include "common.h"
18*6d49e1aeSJan Lentfer #include "ms_funcs.h"
19*6d49e1aeSJan Lentfer #include "mschapv2.h"
20*6d49e1aeSJan Lentfer 
21*6d49e1aeSJan Lentfer const u8 * mschapv2_remove_domain(const u8 *username, size_t *len)
22*6d49e1aeSJan Lentfer {
23*6d49e1aeSJan Lentfer 	size_t i;
24*6d49e1aeSJan Lentfer 
25*6d49e1aeSJan Lentfer 	/*
26*6d49e1aeSJan Lentfer 	 * MSCHAPv2 does not include optional domain name in the
27*6d49e1aeSJan Lentfer 	 * challenge-response calculation, so remove domain prefix
28*6d49e1aeSJan Lentfer 	 * (if present).
29*6d49e1aeSJan Lentfer 	 */
30*6d49e1aeSJan Lentfer 
31*6d49e1aeSJan Lentfer 	for (i = 0; i < *len; i++) {
32*6d49e1aeSJan Lentfer 		if (username[i] == '\\') {
33*6d49e1aeSJan Lentfer 			*len -= i + 1;
34*6d49e1aeSJan Lentfer 			return username + i + 1;
35*6d49e1aeSJan Lentfer 		}
36*6d49e1aeSJan Lentfer 	}
37*6d49e1aeSJan Lentfer 
38*6d49e1aeSJan Lentfer 	return username;
39*6d49e1aeSJan Lentfer }
40*6d49e1aeSJan Lentfer 
41*6d49e1aeSJan Lentfer 
42*6d49e1aeSJan Lentfer void mschapv2_derive_response(const u8 *identity, size_t identity_len,
43*6d49e1aeSJan Lentfer 			      const u8 *password, size_t password_len,
44*6d49e1aeSJan Lentfer 			      int pwhash,
45*6d49e1aeSJan Lentfer 			      const u8 *auth_challenge,
46*6d49e1aeSJan Lentfer 			      const u8 *peer_challenge,
47*6d49e1aeSJan Lentfer 			      u8 *nt_response, u8 *auth_response,
48*6d49e1aeSJan Lentfer 			      u8 *master_key)
49*6d49e1aeSJan Lentfer {
50*6d49e1aeSJan Lentfer 	const u8 *username;
51*6d49e1aeSJan Lentfer 	size_t username_len;
52*6d49e1aeSJan Lentfer 	u8 password_hash[16], password_hash_hash[16];
53*6d49e1aeSJan Lentfer 
54*6d49e1aeSJan Lentfer 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity",
55*6d49e1aeSJan Lentfer 			  identity, identity_len);
56*6d49e1aeSJan Lentfer 	username_len = identity_len;
57*6d49e1aeSJan Lentfer 	username = mschapv2_remove_domain(identity, &username_len);
58*6d49e1aeSJan Lentfer 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username",
59*6d49e1aeSJan Lentfer 			  username, username_len);
60*6d49e1aeSJan Lentfer 
61*6d49e1aeSJan Lentfer 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge",
62*6d49e1aeSJan Lentfer 		    auth_challenge, MSCHAPV2_CHAL_LEN);
63*6d49e1aeSJan Lentfer 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge",
64*6d49e1aeSJan Lentfer 		    peer_challenge, MSCHAPV2_CHAL_LEN);
65*6d49e1aeSJan Lentfer 	wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username",
66*6d49e1aeSJan Lentfer 			  username, username_len);
67*6d49e1aeSJan Lentfer 	/* Authenticator response is not really needed yet, but calculate it
68*6d49e1aeSJan Lentfer 	 * here so that challenges need not be saved. */
69*6d49e1aeSJan Lentfer 	if (pwhash) {
70*6d49e1aeSJan Lentfer 		wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash",
71*6d49e1aeSJan Lentfer 				password, password_len);
72*6d49e1aeSJan Lentfer 		generate_nt_response_pwhash(auth_challenge, peer_challenge,
73*6d49e1aeSJan Lentfer 					    username, username_len,
74*6d49e1aeSJan Lentfer 					    password, nt_response);
75*6d49e1aeSJan Lentfer 		generate_authenticator_response_pwhash(
76*6d49e1aeSJan Lentfer 			password, peer_challenge, auth_challenge,
77*6d49e1aeSJan Lentfer 			username, username_len, nt_response, auth_response);
78*6d49e1aeSJan Lentfer 	} else {
79*6d49e1aeSJan Lentfer 		wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password",
80*6d49e1aeSJan Lentfer 				      password, password_len);
81*6d49e1aeSJan Lentfer 		generate_nt_response(auth_challenge, peer_challenge,
82*6d49e1aeSJan Lentfer 				     username, username_len,
83*6d49e1aeSJan Lentfer 				     password, password_len, nt_response);
84*6d49e1aeSJan Lentfer 		generate_authenticator_response(password, password_len,
85*6d49e1aeSJan Lentfer 						peer_challenge, auth_challenge,
86*6d49e1aeSJan Lentfer 						username, username_len,
87*6d49e1aeSJan Lentfer 						nt_response, auth_response);
88*6d49e1aeSJan Lentfer 	}
89*6d49e1aeSJan Lentfer 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response",
90*6d49e1aeSJan Lentfer 		    nt_response, MSCHAPV2_NT_RESPONSE_LEN);
91*6d49e1aeSJan Lentfer 	wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response",
92*6d49e1aeSJan Lentfer 		    auth_response, MSCHAPV2_AUTH_RESPONSE_LEN);
93*6d49e1aeSJan Lentfer 
94*6d49e1aeSJan Lentfer 	/* Generate master_key here since we have the needed data available. */
95*6d49e1aeSJan Lentfer 	if (pwhash) {
96*6d49e1aeSJan Lentfer 		hash_nt_password_hash(password, password_hash_hash);
97*6d49e1aeSJan Lentfer 	} else {
98*6d49e1aeSJan Lentfer 		nt_password_hash(password, password_len, password_hash);
99*6d49e1aeSJan Lentfer 		hash_nt_password_hash(password_hash, password_hash_hash);
100*6d49e1aeSJan Lentfer 	}
101*6d49e1aeSJan Lentfer 	get_master_key(password_hash_hash, nt_response, master_key);
102*6d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key",
103*6d49e1aeSJan Lentfer 			master_key, MSCHAPV2_MASTER_KEY_LEN);
104*6d49e1aeSJan Lentfer }
105*6d49e1aeSJan Lentfer 
106*6d49e1aeSJan Lentfer 
107*6d49e1aeSJan Lentfer int mschapv2_verify_auth_response(const u8 *auth_response,
108*6d49e1aeSJan Lentfer 				  const u8 *buf, size_t buf_len)
109*6d49e1aeSJan Lentfer {
110*6d49e1aeSJan Lentfer 	u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN];
111*6d49e1aeSJan Lentfer 	if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN ||
112*6d49e1aeSJan Lentfer 	    buf[0] != 'S' || buf[1] != '=' ||
113*6d49e1aeSJan Lentfer 	    hexstr2bin((char *) (buf + 2), recv_response,
114*6d49e1aeSJan Lentfer 		       MSCHAPV2_AUTH_RESPONSE_LEN) ||
115*6d49e1aeSJan Lentfer 	    os_memcmp(auth_response, recv_response,
116*6d49e1aeSJan Lentfer 		      MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
117*6d49e1aeSJan Lentfer 		return -1;
118*6d49e1aeSJan Lentfer 	return 0;
119*6d49e1aeSJan Lentfer }
120