Branch data Line data Source code
1 : : /*
2 : : * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server
3 : : * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : :
11 : : #include "common.h"
12 : : #include "crypto/ms_funcs.h"
13 : : #include "crypto/random.h"
14 : : #include "eap_i.h"
15 : :
16 : :
17 : : struct eap_mschapv2_hdr {
18 : : u8 op_code; /* MSCHAPV2_OP_* */
19 : : u8 mschapv2_id; /* must be changed for challenges, but not for
20 : : * success/failure */
21 : : u8 ms_length[2]; /* Note: misaligned; length - 5 */
22 : : /* followed by data */
23 : : } STRUCT_PACKED;
24 : :
25 : : #define MSCHAPV2_OP_CHALLENGE 1
26 : : #define MSCHAPV2_OP_RESPONSE 2
27 : : #define MSCHAPV2_OP_SUCCESS 3
28 : : #define MSCHAPV2_OP_FAILURE 4
29 : : #define MSCHAPV2_OP_CHANGE_PASSWORD 7
30 : :
31 : : #define MSCHAPV2_RESP_LEN 49
32 : :
33 : : #define ERROR_RESTRICTED_LOGON_HOURS 646
34 : : #define ERROR_ACCT_DISABLED 647
35 : : #define ERROR_PASSWD_EXPIRED 648
36 : : #define ERROR_NO_DIALIN_PERMISSION 649
37 : : #define ERROR_AUTHENTICATION_FAILURE 691
38 : : #define ERROR_CHANGING_PASSWORD 709
39 : :
40 : : #define PASSWD_CHANGE_CHAL_LEN 16
41 : : #define MSCHAPV2_KEY_LEN 16
42 : :
43 : :
44 : : #define CHALLENGE_LEN 16
45 : :
46 : : struct eap_mschapv2_data {
47 : : u8 auth_challenge[CHALLENGE_LEN];
48 : : int auth_challenge_from_tls;
49 : : u8 *peer_challenge;
50 : : u8 auth_response[20];
51 : : enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state;
52 : : u8 resp_mschapv2_id;
53 : : u8 master_key[16];
54 : : int master_key_valid;
55 : : };
56 : :
57 : :
58 : 26 : static void * eap_mschapv2_init(struct eap_sm *sm)
59 : : {
60 : : struct eap_mschapv2_data *data;
61 : :
62 : 26 : data = os_zalloc(sizeof(*data));
63 [ - + ]: 26 : if (data == NULL)
64 : 0 : return NULL;
65 : 26 : data->state = CHALLENGE;
66 : :
67 [ - + ]: 26 : if (sm->auth_challenge) {
68 : 0 : os_memcpy(data->auth_challenge, sm->auth_challenge,
69 : : CHALLENGE_LEN);
70 : 0 : data->auth_challenge_from_tls = 1;
71 : : }
72 : :
73 [ - + ]: 26 : if (sm->peer_challenge) {
74 : 0 : data->peer_challenge = os_malloc(CHALLENGE_LEN);
75 [ # # ]: 0 : if (data->peer_challenge == NULL) {
76 : 0 : os_free(data);
77 : 0 : return NULL;
78 : : }
79 : 0 : os_memcpy(data->peer_challenge, sm->peer_challenge,
80 : : CHALLENGE_LEN);
81 : : }
82 : :
83 : 26 : return data;
84 : : }
85 : :
86 : :
87 : 26 : static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
88 : : {
89 : 26 : struct eap_mschapv2_data *data = priv;
90 [ - + ]: 26 : if (data == NULL)
91 : 26 : return;
92 : :
93 : 26 : os_free(data->peer_challenge);
94 : 26 : os_free(data);
95 : : }
96 : :
97 : :
98 : 26 : static struct wpabuf * eap_mschapv2_build_challenge(
99 : : struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
100 : : {
101 : : struct wpabuf *req;
102 : : struct eap_mschapv2_hdr *ms;
103 : : size_t ms_len;
104 : :
105 [ + - - + ]: 52 : if (!data->auth_challenge_from_tls &&
106 : 26 : random_get_bytes(data->auth_challenge, CHALLENGE_LEN)) {
107 : 0 : wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random "
108 : : "data");
109 : 0 : data->state = FAILURE;
110 : 0 : return NULL;
111 : : }
112 : :
113 : 26 : ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
114 : 26 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
115 : : EAP_CODE_REQUEST, id);
116 [ - + ]: 26 : if (req == NULL) {
117 : 0 : wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
118 : : " for request");
119 : 0 : data->state = FAILURE;
120 : 0 : return NULL;
121 : : }
122 : :
123 : 26 : ms = wpabuf_put(req, sizeof(*ms));
124 : 26 : ms->op_code = MSCHAPV2_OP_CHALLENGE;
125 : 26 : ms->mschapv2_id = id;
126 : 26 : WPA_PUT_BE16(ms->ms_length, ms_len);
127 : :
128 : 26 : wpabuf_put_u8(req, CHALLENGE_LEN);
129 [ + - ]: 26 : if (!data->auth_challenge_from_tls)
130 : 26 : wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
131 : : else
132 : 0 : wpabuf_put(req, CHALLENGE_LEN);
133 : 26 : wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
134 : 26 : data->auth_challenge, CHALLENGE_LEN);
135 : 26 : wpabuf_put_data(req, sm->server_id, sm->server_id_len);
136 : :
137 : 26 : return req;
138 : : }
139 : :
140 : :
141 : 16 : static struct wpabuf * eap_mschapv2_build_success_req(
142 : : struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
143 : : {
144 : : struct wpabuf *req;
145 : : struct eap_mschapv2_hdr *ms;
146 : : u8 *msg;
147 : 16 : char *message = "OK";
148 : : size_t ms_len;
149 : :
150 : 16 : ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
151 : 16 : os_strlen(message);
152 : 16 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
153 : : EAP_CODE_REQUEST, id);
154 [ - + ]: 16 : if (req == NULL) {
155 : 0 : wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
156 : : " for request");
157 : 0 : data->state = FAILURE;
158 : 0 : return NULL;
159 : : }
160 : :
161 : 16 : ms = wpabuf_put(req, sizeof(*ms));
162 : 16 : ms->op_code = MSCHAPV2_OP_SUCCESS;
163 : 16 : ms->mschapv2_id = data->resp_mschapv2_id;
164 : 16 : WPA_PUT_BE16(ms->ms_length, ms_len);
165 : 16 : msg = (u8 *) (ms + 1);
166 : :
167 : 16 : wpabuf_put_u8(req, 'S');
168 : 16 : wpabuf_put_u8(req, '=');
169 : 16 : wpa_snprintf_hex_uppercase(
170 : 16 : wpabuf_put(req, sizeof(data->auth_response) * 2),
171 : : sizeof(data->auth_response) * 2 + 1,
172 : 16 : data->auth_response, sizeof(data->auth_response));
173 : 16 : wpabuf_put_u8(req, ' ');
174 : 16 : wpabuf_put_u8(req, 'M');
175 : 16 : wpabuf_put_u8(req, '=');
176 : 16 : wpabuf_put_data(req, message, os_strlen(message));
177 : :
178 : 16 : wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
179 : : msg, ms_len - sizeof(*ms));
180 : :
181 : 16 : return req;
182 : : }
183 : :
184 : :
185 : 2 : static struct wpabuf * eap_mschapv2_build_failure_req(
186 : : struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
187 : : {
188 : : struct wpabuf *req;
189 : : struct eap_mschapv2_hdr *ms;
190 : 2 : char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 "
191 : : "M=FAILED";
192 : : size_t ms_len;
193 : :
194 : 2 : ms_len = sizeof(*ms) + os_strlen(message);
195 : 2 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
196 : : EAP_CODE_REQUEST, id);
197 [ - + ]: 2 : if (req == NULL) {
198 : 0 : wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
199 : : " for request");
200 : 0 : data->state = FAILURE;
201 : 0 : return NULL;
202 : : }
203 : :
204 : 2 : ms = wpabuf_put(req, sizeof(*ms));
205 : 2 : ms->op_code = MSCHAPV2_OP_FAILURE;
206 : 2 : ms->mschapv2_id = data->resp_mschapv2_id;
207 : 2 : WPA_PUT_BE16(ms->ms_length, ms_len);
208 : :
209 : 2 : wpabuf_put_data(req, message, os_strlen(message));
210 : :
211 : 2 : wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message",
212 : : (u8 *) message, os_strlen(message));
213 : :
214 : 2 : return req;
215 : : }
216 : :
217 : :
218 : 44 : static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv,
219 : : u8 id)
220 : : {
221 : 44 : struct eap_mschapv2_data *data = priv;
222 : :
223 [ + + + - ]: 44 : switch (data->state) {
224 : : case CHALLENGE:
225 : 26 : return eap_mschapv2_build_challenge(sm, data, id);
226 : : case SUCCESS_REQ:
227 : 16 : return eap_mschapv2_build_success_req(sm, data, id);
228 : : case FAILURE_REQ:
229 : 2 : return eap_mschapv2_build_failure_req(sm, data, id);
230 : : default:
231 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
232 : 0 : "buildReq", data->state);
233 : 0 : break;
234 : : }
235 : 44 : return NULL;
236 : : }
237 : :
238 : :
239 : 36 : static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv,
240 : : struct wpabuf *respData)
241 : : {
242 : 36 : struct eap_mschapv2_data *data = priv;
243 : : struct eap_mschapv2_hdr *resp;
244 : : const u8 *pos;
245 : : size_t len;
246 : :
247 : 36 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
248 : : &len);
249 [ - + ][ + - ]: 36 : if (pos == NULL || len < 1) {
250 : 0 : wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
251 : 0 : return TRUE;
252 : : }
253 : :
254 : 36 : resp = (struct eap_mschapv2_hdr *) pos;
255 [ + + ][ - + ]: 36 : if (data->state == CHALLENGE &&
256 : 18 : resp->op_code != MSCHAPV2_OP_RESPONSE) {
257 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - "
258 : 0 : "ignore op %d", resp->op_code);
259 : 0 : return TRUE;
260 : : }
261 : :
262 [ + + ][ - + ]: 36 : if (data->state == SUCCESS_REQ &&
263 [ # # ]: 0 : resp->op_code != MSCHAPV2_OP_SUCCESS &&
264 : 0 : resp->op_code != MSCHAPV2_OP_FAILURE) {
265 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or "
266 : 0 : "Failure - ignore op %d", resp->op_code);
267 : 0 : return TRUE;
268 : : }
269 : :
270 [ + + ][ - + ]: 36 : if (data->state == FAILURE_REQ &&
271 : 2 : resp->op_code != MSCHAPV2_OP_FAILURE) {
272 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure "
273 : 0 : "- ignore op %d", resp->op_code);
274 : 0 : return TRUE;
275 : : }
276 : :
277 : 36 : return FALSE;
278 : : }
279 : :
280 : :
281 : 18 : static void eap_mschapv2_process_response(struct eap_sm *sm,
282 : : struct eap_mschapv2_data *data,
283 : : struct wpabuf *respData)
284 : : {
285 : : struct eap_mschapv2_hdr *resp;
286 : : const u8 *pos, *end, *peer_challenge, *nt_response, *name;
287 : : u8 flags;
288 : : size_t len, name_len, i;
289 : : u8 expected[24];
290 : : const u8 *username, *user;
291 : : size_t username_len, user_len;
292 : : int res;
293 : :
294 : 18 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
295 : : &len);
296 [ - + ][ + - ]: 18 : if (pos == NULL || len < 1)
297 : 0 : return; /* Should not happen - frame already validated */
298 : :
299 : 18 : end = pos + len;
300 : 18 : resp = (struct eap_mschapv2_hdr *) pos;
301 : 18 : pos = (u8 *) (resp + 1);
302 : :
303 [ + - ][ + - ]: 18 : if (len < sizeof(*resp) + 1 + 49 ||
304 [ - + ]: 18 : resp->op_code != MSCHAPV2_OP_RESPONSE ||
305 : 18 : pos[0] != 49) {
306 : 0 : wpa_hexdump_buf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response",
307 : : respData);
308 : 0 : data->state = FAILURE;
309 : 0 : return;
310 : : }
311 : 18 : data->resp_mschapv2_id = resp->mschapv2_id;
312 : 18 : pos++;
313 : 18 : peer_challenge = pos;
314 : 18 : pos += 16 + 8;
315 : 18 : nt_response = pos;
316 : 18 : pos += 24;
317 : 18 : flags = *pos++;
318 : 18 : name = pos;
319 : 18 : name_len = end - name;
320 : :
321 [ - + ]: 18 : if (data->peer_challenge) {
322 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
323 : : "Peer-Challenge");
324 : 0 : peer_challenge = data->peer_challenge;
325 : : }
326 : 18 : wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
327 : : peer_challenge, 16);
328 : 18 : wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);
329 : 18 : wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
330 : 18 : wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
331 : :
332 : : /* MSCHAPv2 does not include optional domain name in the
333 : : * challenge-response calculation, so remove domain prefix
334 : : * (if present). */
335 : 18 : username = sm->identity;
336 : 18 : username_len = sm->identity_len;
337 [ + + ]: 90 : for (i = 0; i < username_len; i++) {
338 [ - + ]: 72 : if (username[i] == '\\') {
339 : 0 : username_len -= i + 1;
340 : 0 : username += i + 1;
341 : 0 : break;
342 : : }
343 : : }
344 : :
345 : 18 : user = name;
346 : 18 : user_len = name_len;
347 [ + + ]: 90 : for (i = 0; i < user_len; i++) {
348 [ - + ]: 72 : if (user[i] == '\\') {
349 : 0 : user_len -= i + 1;
350 : 0 : user += i + 1;
351 : 0 : break;
352 : : }
353 : : }
354 : :
355 [ + - ][ - + ]: 18 : if (username_len != user_len ||
356 : 18 : os_memcmp(username, user, username_len) != 0) {
357 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
358 : 0 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user "
359 : : "name", username, username_len);
360 : 0 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user "
361 : : "name", user, user_len);
362 : 0 : data->state = FAILURE;
363 : 0 : return;
364 : : }
365 : :
366 : 18 : wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name",
367 : : username, username_len);
368 : :
369 [ - + ]: 18 : if (sm->user->password_hash) {
370 : 0 : res = generate_nt_response_pwhash(data->auth_challenge,
371 : : peer_challenge,
372 : : username, username_len,
373 : 0 : sm->user->password,
374 : : expected);
375 : : } else {
376 : 18 : res = generate_nt_response(data->auth_challenge,
377 : : peer_challenge,
378 : : username, username_len,
379 : 18 : sm->user->password,
380 : 18 : sm->user->password_len,
381 : : expected);
382 : : }
383 [ - + ]: 18 : if (res) {
384 : 0 : data->state = FAILURE;
385 : 0 : return;
386 : : }
387 : :
388 [ + + ]: 18 : if (os_memcmp(nt_response, expected, 24) == 0) {
389 : : const u8 *pw_hash;
390 : : u8 pw_hash_buf[16], pw_hash_hash[16];
391 : :
392 : 16 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response");
393 : 16 : data->state = SUCCESS_REQ;
394 : :
395 : : /* Authenticator response is not really needed yet, but
396 : : * calculate it here so that peer_challenge and username need
397 : : * not be saved. */
398 [ - + ]: 16 : if (sm->user->password_hash) {
399 : 0 : pw_hash = sm->user->password;
400 : : } else {
401 [ - + ]: 16 : if (nt_password_hash(sm->user->password,
402 : 16 : sm->user->password_len,
403 : : pw_hash_buf) < 0) {
404 : 0 : data->state = FAILURE;
405 : 0 : return;
406 : : }
407 : 16 : pw_hash = pw_hash_buf;
408 : : }
409 : 16 : generate_authenticator_response_pwhash(
410 : 16 : pw_hash, peer_challenge, data->auth_challenge,
411 : : username, username_len, nt_response,
412 : 16 : data->auth_response);
413 : :
414 : 16 : hash_nt_password_hash(pw_hash, pw_hash_hash);
415 : 16 : get_master_key(pw_hash_hash, nt_response, data->master_key);
416 : 16 : data->master_key_valid = 1;
417 : 16 : wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
418 : 16 : data->master_key, MSCHAPV2_KEY_LEN);
419 : : } else {
420 : 2 : wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response",
421 : : expected, 24);
422 : 2 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response");
423 : 18 : data->state = FAILURE_REQ;
424 : : }
425 : : }
426 : :
427 : :
428 : 16 : static void eap_mschapv2_process_success_resp(struct eap_sm *sm,
429 : : struct eap_mschapv2_data *data,
430 : : struct wpabuf *respData)
431 : : {
432 : : struct eap_mschapv2_hdr *resp;
433 : : const u8 *pos;
434 : : size_t len;
435 : :
436 : 16 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
437 : : &len);
438 [ - + ][ + - ]: 16 : if (pos == NULL || len < 1)
439 : 16 : return; /* Should not happen - frame already validated */
440 : :
441 : 16 : resp = (struct eap_mschapv2_hdr *) pos;
442 : :
443 [ + - ]: 16 : if (resp->op_code == MSCHAPV2_OP_SUCCESS) {
444 : 16 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response"
445 : : " - authentication completed successfully");
446 : 16 : data->state = SUCCESS;
447 : : } else {
448 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success "
449 : : "Response - peer rejected authentication");
450 : 0 : data->state = FAILURE;
451 : : }
452 : : }
453 : :
454 : :
455 : 2 : static void eap_mschapv2_process_failure_resp(struct eap_sm *sm,
456 : : struct eap_mschapv2_data *data,
457 : : struct wpabuf *respData)
458 : : {
459 : : struct eap_mschapv2_hdr *resp;
460 : : const u8 *pos;
461 : : size_t len;
462 : :
463 : 2 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
464 : : &len);
465 [ - + ][ + - ]: 2 : if (pos == NULL || len < 1)
466 : 2 : return; /* Should not happen - frame already validated */
467 : :
468 : 2 : resp = (struct eap_mschapv2_hdr *) pos;
469 : :
470 [ + - ]: 2 : if (resp->op_code == MSCHAPV2_OP_FAILURE) {
471 : 2 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response"
472 : : " - authentication failed");
473 : : } else {
474 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure "
475 : : "Response - authentication failed");
476 : : }
477 : :
478 : 2 : data->state = FAILURE;
479 : : }
480 : :
481 : :
482 : 36 : static void eap_mschapv2_process(struct eap_sm *sm, void *priv,
483 : : struct wpabuf *respData)
484 : : {
485 : 36 : struct eap_mschapv2_data *data = priv;
486 : :
487 [ + - ][ - + ]: 36 : if (sm->user == NULL || sm->user->password == NULL) {
488 : 0 : wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
489 : 0 : data->state = FAILURE;
490 : 36 : return;
491 : : }
492 : :
493 [ + + + - ]: 36 : switch (data->state) {
494 : : case CHALLENGE:
495 : 18 : eap_mschapv2_process_response(sm, data, respData);
496 : 18 : break;
497 : : case SUCCESS_REQ:
498 : 16 : eap_mschapv2_process_success_resp(sm, data, respData);
499 : 16 : break;
500 : : case FAILURE_REQ:
501 : 2 : eap_mschapv2_process_failure_resp(sm, data, respData);
502 : 2 : break;
503 : : default:
504 : 0 : wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
505 : 0 : "process", data->state);
506 : 0 : break;
507 : : }
508 : : }
509 : :
510 : :
511 : 36 : static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv)
512 : : {
513 : 36 : struct eap_mschapv2_data *data = priv;
514 [ + + ][ + + ]: 36 : return data->state == SUCCESS || data->state == FAILURE;
515 : : }
516 : :
517 : :
518 : 12 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
519 : : {
520 : 12 : struct eap_mschapv2_data *data = priv;
521 : : u8 *key;
522 : :
523 [ + - ][ - + ]: 12 : if (data->state != SUCCESS || !data->master_key_valid)
524 : 0 : return NULL;
525 : :
526 : 12 : *len = 2 * MSCHAPV2_KEY_LEN;
527 : 12 : key = os_malloc(*len);
528 [ - + ]: 12 : if (key == NULL)
529 : 0 : return NULL;
530 : : /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
531 : 12 : get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
532 : 12 : get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
533 : : MSCHAPV2_KEY_LEN, 1, 1);
534 : 12 : wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
535 : :
536 : 12 : return key;
537 : : }
538 : :
539 : :
540 : 18 : static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv)
541 : : {
542 : 18 : struct eap_mschapv2_data *data = priv;
543 : 18 : return data->state == SUCCESS;
544 : : }
545 : :
546 : :
547 : 2 : int eap_server_mschapv2_register(void)
548 : : {
549 : : struct eap_method *eap;
550 : : int ret;
551 : :
552 : 2 : eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
553 : : EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
554 : : "MSCHAPV2");
555 [ - + ]: 2 : if (eap == NULL)
556 : 0 : return -1;
557 : :
558 : 2 : eap->init = eap_mschapv2_init;
559 : 2 : eap->reset = eap_mschapv2_reset;
560 : 2 : eap->buildReq = eap_mschapv2_buildReq;
561 : 2 : eap->check = eap_mschapv2_check;
562 : 2 : eap->process = eap_mschapv2_process;
563 : 2 : eap->isDone = eap_mschapv2_isDone;
564 : 2 : eap->getKey = eap_mschapv2_getKey;
565 : 2 : eap->isSuccess = eap_mschapv2_isSuccess;
566 : :
567 : 2 : ret = eap_server_method_register(eap);
568 [ - + ]: 2 : if (ret)
569 : 0 : eap_server_method_free(eap);
570 : 2 : return ret;
571 : : }
|