1 /*
2  * MSCHAPV2
3  */
4 
5 #ifdef EAP_MSCHAPv2
6 
7 #include "utils/includes.h"
8 #include "utils/common.h"
9 #include "crypto/ms_funcs.h"
10 #include "eap_peer/mschapv2.h"
11 
mschapv2_remove_domain(const u8 * username,size_t * len)12 const u8 * mschapv2_remove_domain(const u8 *username, size_t *len)
13 {
14 	size_t i;
15 
16 	/*
17 	 * MSCHAPV2 does not include optional domain name in the
18 	 * challenge-response calculation, so remove domain prefix
19 	 * (if present)
20 	 */
21 	for (i = 0; i < *len; i++) {
22 		if (username[i] == '\\') {
23 			*len -= i + 1;
24 			return username + i + 1;
25 		}
26 	}
27 
28 	return username;
29 }
30 
mschapv2_derive_response(const u8 * identity,size_t identity_len,const u8 * password,size_t password_len,int pwhash,const u8 * auth_challenge,const u8 * peer_challenge,u8 * nt_response,u8 * auth_response,u8 * master_key)31 int mschapv2_derive_response(const u8 *identity, size_t identity_len,
32 			 const u8 *password, size_t password_len,
33 			 int pwhash,
34 			 const u8 *auth_challenge,
35 			 const u8 *peer_challenge,
36 			 u8 *nt_response, u8 *auth_response,
37 			 u8 *master_key)
38 {
39 	const u8 *username;
40 	size_t username_len;
41 	u8 password_hash[16], password_hash_hash[16];
42 
43 	username_len = identity_len;
44 	username = mschapv2_remove_domain(identity, &username_len);
45 
46 	if (pwhash) {
47 		if (generate_nt_response_pwhash(auth_challenge, peer_challenge,
48 						username, username_len,
49 						password, nt_response) ||
50 		    generate_authenticator_response_pwhash(
51 				password, peer_challenge, auth_challenge,
52 				username, username_len, nt_response,
53 				auth_response))
54 			return -1;
55 	} else {
56 		if (generate_nt_response(auth_challenge, peer_challenge,
57 					 username, username_len,
58 					 password, password_len,
59 					 nt_response) ||
60 		    generate_authenticator_response(password, password_len,
61 						    peer_challenge,
62 						    auth_challenge,
63 						    username, username_len,
64 						    nt_response,
65 						    auth_response))
66 			return -1;
67 	}
68 
69 	if (pwhash) {
70 		if (hash_nt_password_hash(password, password_hash_hash))
71 			return -1;
72 	} else {
73 		if (nt_password_hash(password, password_len, password_hash) ||
74 		    hash_nt_password_hash(password_hash, password_hash_hash))
75 			return -1;
76 	}
77 	if (get_master_key(password_hash_hash, nt_response, master_key))
78 		return -1;
79 
80 	return 0;
81 }
82 
mschapv2_verify_auth_response(const u8 * auth_response,const u8 * buf,size_t buf_len)83 int mschapv2_verify_auth_response(const u8 *auth_response,
84 			      const u8 *buf, size_t buf_len)
85 {
86 	u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN];
87 	if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN ||
88 	    buf[0] != 'S' || buf[1] != '=' ||
89 	    hexstr2bin((char *)(buf + 2), recv_response,
90 		       MSCHAPV2_AUTH_RESPONSE_LEN) ||
91 	    os_memcmp(auth_response, recv_response,
92 		      MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
93 		return -1;
94 	return 0;
95 }
96 
97 #endif /* EAP_MSCHAPv2 */
98