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