3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "crypto/ms_funcs.h"
21 const u8
* mschapv2_remove_domain(const u8
*username
, size_t *len
)
26 * MSCHAPv2 does not include optional domain name in the
27 * challenge-response calculation, so remove domain prefix
31 for (i
= 0; i
< *len
; i
++) {
32 if (username
[i
] == '\\') {
34 return username
+ i
+ 1;
42 int mschapv2_derive_response(const u8
*identity
, size_t identity_len
,
43 const u8
*password
, size_t password_len
,
45 const u8
*auth_challenge
,
46 const u8
*peer_challenge
,
47 u8
*nt_response
, u8
*auth_response
,
52 u8 password_hash
[16], password_hash_hash
[16];
54 wpa_hexdump_ascii(MSG_DEBUG
, "MSCHAPV2: Identity",
55 identity
, identity_len
);
56 username_len
= identity_len
;
57 username
= mschapv2_remove_domain(identity
, &username_len
);
58 wpa_hexdump_ascii(MSG_DEBUG
, "MSCHAPV2: Username",
59 username
, username_len
);
61 wpa_hexdump(MSG_DEBUG
, "MSCHAPV2: auth_challenge",
62 auth_challenge
, MSCHAPV2_CHAL_LEN
);
63 wpa_hexdump(MSG_DEBUG
, "MSCHAPV2: peer_challenge",
64 peer_challenge
, MSCHAPV2_CHAL_LEN
);
65 wpa_hexdump_ascii(MSG_DEBUG
, "MSCHAPV2: username",
66 username
, username_len
);
67 /* Authenticator response is not really needed yet, but calculate it
68 * here so that challenges need not be saved. */
70 wpa_hexdump_key(MSG_DEBUG
, "MSCHAPV2: password hash",
71 password
, password_len
);
72 generate_nt_response_pwhash(auth_challenge
, peer_challenge
,
73 username
, username_len
,
74 password
, nt_response
);
75 generate_authenticator_response_pwhash(
76 password
, peer_challenge
, auth_challenge
,
77 username
, username_len
, nt_response
, auth_response
);
79 wpa_hexdump_ascii_key(MSG_DEBUG
, "MSCHAPV2: password",
80 password
, password_len
);
81 generate_nt_response(auth_challenge
, peer_challenge
,
82 username
, username_len
,
83 password
, password_len
, nt_response
);
84 generate_authenticator_response(password
, password_len
,
85 peer_challenge
, auth_challenge
,
86 username
, username_len
,
87 nt_response
, auth_response
);
89 wpa_hexdump(MSG_DEBUG
, "MSCHAPV2: NT Response",
90 nt_response
, MSCHAPV2_NT_RESPONSE_LEN
);
91 wpa_hexdump(MSG_DEBUG
, "MSCHAPV2: Auth Response",
92 auth_response
, MSCHAPV2_AUTH_RESPONSE_LEN
);
94 /* Generate master_key here since we have the needed data available. */
96 if (hash_nt_password_hash(password
, password_hash_hash
))
99 if (nt_password_hash(password
, password_len
, password_hash
) ||
100 hash_nt_password_hash(password_hash
, password_hash_hash
))
103 get_master_key(password_hash_hash
, nt_response
, master_key
);
104 wpa_hexdump_key(MSG_DEBUG
, "MSCHAPV2: Master Key",
105 master_key
, MSCHAPV2_MASTER_KEY_LEN
);
111 int mschapv2_verify_auth_response(const u8
*auth_response
,
112 const u8
*buf
, size_t buf_len
)
114 u8 recv_response
[MSCHAPV2_AUTH_RESPONSE_LEN
];
115 if (buf_len
< 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN
||
116 buf
[0] != 'S' || buf
[1] != '=' ||
117 hexstr2bin((char *) (buf
+ 2), recv_response
,
118 MSCHAPV2_AUTH_RESPONSE_LEN
) ||
119 os_memcmp(auth_response
, recv_response
,
120 MSCHAPV2_AUTH_RESPONSE_LEN
) != 0)