More minor IPI work.
[dragonfly/vkernel-mp.git] / contrib / hostapd-0.4.9 / eap_ttls.c
blob569b1c3cc2fb35af62c7d8a2453dad802ae2eddb
1 /*
2 * hostapd / EAP-TTLS (draft-ietf-pppext-eap-ttls-05.txt)
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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
10 * license.
12 * See README and COPYING for more details.
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <netinet/in.h>
20 #include "hostapd.h"
21 #include "common.h"
22 #include "eap_i.h"
23 #include "eap_tls_common.h"
24 #include "ms_funcs.h"
25 #include "md5.h"
26 #include "crypto.h"
27 #include "tls.h"
28 #include "eap_ttls.h"
30 #define EAP_TTLS_VERSION 0
33 static void eap_ttls_reset(struct eap_sm *sm, void *priv);
36 struct eap_ttls_data {
37 struct eap_ssl_data ssl;
38 enum {
39 START, PHASE1, PHASE2_START, PHASE2_METHOD,
40 PHASE2_MSCHAPV2_RESP, SUCCESS, FAILURE
41 } state;
43 int ttls_version;
44 const struct eap_method *phase2_method;
45 void *phase2_priv;
46 int mschapv2_resp_ok;
47 u8 mschapv2_auth_response[20];
48 u8 mschapv2_ident;
52 static const char * eap_ttls_state_txt(int state)
54 switch (state) {
55 case START:
56 return "START";
57 case PHASE1:
58 return "PHASE1";
59 case PHASE2_START:
60 return "PHASE2_START";
61 case PHASE2_METHOD:
62 return "PHASE2_METHOD";
63 case PHASE2_MSCHAPV2_RESP:
64 return "PHASE2_MSCHAPV2_RESP";
65 case SUCCESS:
66 return "SUCCESS";
67 case FAILURE:
68 return "FAILURE";
69 default:
70 return "Unknown?!";
75 static void eap_ttls_state(struct eap_ttls_data *data, int state)
77 wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s",
78 eap_ttls_state_txt(data->state),
79 eap_ttls_state_txt(state));
80 data->state = state;
84 static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
85 int mandatory, size_t len)
87 struct ttls_avp_vendor *avp;
88 u8 flags;
89 size_t hdrlen;
91 avp = (struct ttls_avp_vendor *) avphdr;
92 flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
93 if (vendor_id) {
94 flags |= AVP_FLAGS_VENDOR;
95 hdrlen = sizeof(*avp);
96 avp->vendor_id = host_to_be32(vendor_id);
97 } else {
98 hdrlen = sizeof(struct ttls_avp);
101 avp->avp_code = host_to_be32(avp_code);
102 avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));
104 return avphdr + hdrlen;
108 static int eap_ttls_avp_encapsulate(u8 **resp, size_t *resp_len, u32 avp_code,
109 int mandatory)
111 u8 *avp, *pos;
113 avp = malloc(sizeof(struct ttls_avp) + *resp_len + 4);
114 if (avp == NULL) {
115 free(*resp);
116 *resp_len = 0;
117 return -1;
120 pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len);
121 memcpy(pos, *resp, *resp_len);
122 pos += *resp_len;
123 AVP_PAD(avp, pos);
124 free(*resp);
125 *resp = avp;
126 *resp_len = pos - avp;
127 return 0;
131 struct eap_ttls_avp {
132 /* Note: eap is allocated memory; caller is responsible for freeing
133 * it. All the other pointers are pointing to the packet data, i.e.,
134 * they must not be freed separately. */
135 u8 *eap;
136 size_t eap_len;
137 u8 *user_name;
138 size_t user_name_len;
139 u8 *user_password;
140 size_t user_password_len;
141 u8 *chap_challenge;
142 size_t chap_challenge_len;
143 u8 *chap_password;
144 size_t chap_password_len;
145 u8 *mschap_challenge;
146 size_t mschap_challenge_len;
147 u8 *mschap_response;
148 size_t mschap_response_len;
149 u8 *mschap2_response;
150 size_t mschap2_response_len;
154 static int eap_ttls_avp_parse(u8 *buf, size_t len, struct eap_ttls_avp *parse)
156 struct ttls_avp *avp;
157 u8 *pos;
158 int left;
160 pos = buf;
161 left = len;
162 memset(parse, 0, sizeof(*parse));
164 while (left > 0) {
165 u32 avp_code, avp_length, vendor_id = 0;
166 u8 avp_flags, *dpos;
167 size_t pad, dlen;
168 avp = (struct ttls_avp *) pos;
169 avp_code = be_to_host32(avp->avp_code);
170 avp_length = be_to_host32(avp->avp_length);
171 avp_flags = (avp_length >> 24) & 0xff;
172 avp_length &= 0xffffff;
173 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
174 "length=%d", (int) avp_code, avp_flags,
175 (int) avp_length);
176 if (avp_length > left) {
177 wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
178 "(len=%d, left=%d) - dropped",
179 (int) avp_length, left);
180 return -1;
182 dpos = (u8 *) (avp + 1);
183 dlen = avp_length - sizeof(*avp);
184 if (avp_flags & AVP_FLAGS_VENDOR) {
185 if (dlen < 4) {
186 wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP "
187 "underflow");
188 return -1;
190 vendor_id = be_to_host32(* (u32 *) dpos);
191 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
192 (int) vendor_id);
193 dpos += 4;
194 dlen -= 4;
197 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
199 if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
200 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
201 if (parse->eap == NULL) {
202 parse->eap = malloc(dlen);
203 if (parse->eap == NULL) {
204 wpa_printf(MSG_WARNING, "EAP-TTLS: "
205 "failed to allocate memory "
206 "for Phase 2 EAP data");
207 return -1;
209 memcpy(parse->eap, dpos, dlen);
210 parse->eap_len = dlen;
211 } else {
212 u8 *neweap = realloc(parse->eap,
213 parse->eap_len + dlen);
214 if (neweap == NULL) {
215 wpa_printf(MSG_WARNING, "EAP-TTLS: "
216 "failed to allocate memory "
217 "for Phase 2 EAP data");
218 free(parse->eap);
219 parse->eap = NULL;
220 return -1;
222 memcpy(neweap + parse->eap_len, dpos, dlen);
223 parse->eap = neweap;
224 parse->eap_len += dlen;
226 } else if (vendor_id == 0 &&
227 avp_code == RADIUS_ATTR_USER_NAME) {
228 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name",
229 dpos, dlen);
230 parse->user_name = dpos;
231 parse->user_name_len = dlen;
232 } else if (vendor_id == 0 &&
233 avp_code == RADIUS_ATTR_USER_PASSWORD) {
234 u8 *password = dpos;
235 size_t password_len = dlen;
236 while (password_len > 0 &&
237 password[password_len - 1] == '\0') {
238 password_len--;
240 wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: "
241 "User-Password (PAP)",
242 password, password_len);
243 parse->user_password = password;
244 parse->user_password_len = password_len;
245 } else if (vendor_id == 0 &&
246 avp_code == RADIUS_ATTR_CHAP_CHALLENGE) {
247 wpa_hexdump(MSG_DEBUG,
248 "EAP-TTLS: CHAP-Challenge (CHAP)",
249 dpos, dlen);
250 parse->chap_challenge = dpos;
251 parse->chap_challenge_len = dlen;
252 } else if (vendor_id == 0 &&
253 avp_code == RADIUS_ATTR_CHAP_PASSWORD) {
254 wpa_hexdump(MSG_DEBUG,
255 "EAP-TTLS: CHAP-Password (CHAP)",
256 dpos, dlen);
257 parse->chap_password = dpos;
258 parse->chap_password_len = dlen;
259 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
260 avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) {
261 wpa_hexdump(MSG_DEBUG,
262 "EAP-TTLS: MS-CHAP-Challenge",
263 dpos, dlen);
264 parse->mschap_challenge = dpos;
265 parse->mschap_challenge_len = dlen;
266 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
267 avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) {
268 wpa_hexdump(MSG_DEBUG,
269 "EAP-TTLS: MS-CHAP-Response (MSCHAP)",
270 dpos, dlen);
271 parse->mschap_response = dpos;
272 parse->mschap_response_len = dlen;
273 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
274 avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) {
275 wpa_hexdump(MSG_DEBUG,
276 "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)",
277 dpos, dlen);
278 parse->mschap2_response = dpos;
279 parse->mschap2_response_len = dlen;
280 } else if (avp_flags & AVP_FLAGS_MANDATORY) {
281 wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported "
282 "mandatory AVP code %d vendor_id %d - "
283 "dropped", (int) avp_code, (int) vendor_id);
284 return -1;
285 } else {
286 wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported "
287 "AVP code %d vendor_id %d",
288 (int) avp_code, (int) vendor_id);
291 pad = (4 - (avp_length & 3)) & 3;
292 pos += avp_length + pad;
293 left -= avp_length + pad;
296 return 0;
300 static void * eap_ttls_init(struct eap_sm *sm)
302 struct eap_ttls_data *data;
304 data = malloc(sizeof(*data));
305 if (data == NULL)
306 return data;
307 memset(data, 0, sizeof(*data));
308 data->ttls_version = EAP_TTLS_VERSION;
309 data->state = START;
311 if (eap_tls_ssl_init(sm, &data->ssl, 0)) {
312 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
313 eap_ttls_reset(sm, data);
314 return NULL;
317 return data;
321 static void eap_ttls_reset(struct eap_sm *sm, void *priv)
323 struct eap_ttls_data *data = priv;
324 if (data == NULL)
325 return;
326 if (data->phase2_priv && data->phase2_method)
327 data->phase2_method->reset(sm, data->phase2_priv);
328 eap_tls_ssl_deinit(sm, &data->ssl);
329 free(data);
333 static u8 * eap_ttls_build_start(struct eap_sm *sm, struct eap_ttls_data *data,
334 int id, size_t *reqDataLen)
336 struct eap_hdr *req;
337 u8 *pos;
339 *reqDataLen = sizeof(*req) + 2;
340 req = malloc(*reqDataLen);
341 if (req == NULL) {
342 wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for"
343 " request");
344 eap_ttls_state(data, FAILURE);
345 return NULL;
348 req->code = EAP_CODE_REQUEST;
349 req->identifier = id;
350 req->length = htons(*reqDataLen);
351 pos = (u8 *) (req + 1);
352 *pos++ = EAP_TYPE_TTLS;
353 *pos = EAP_TLS_FLAGS_START | data->ttls_version;
355 eap_ttls_state(data, PHASE1);
357 return (u8 *) req;
361 static u8 * eap_ttls_build_req(struct eap_sm *sm, struct eap_ttls_data *data,
362 int id, size_t *reqDataLen)
364 int res;
365 u8 *req;
367 res = eap_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TTLS,
368 data->ttls_version, id, &req,
369 reqDataLen);
371 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
372 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, starting "
373 "Phase2");
374 eap_ttls_state(data, PHASE2_START);
377 if (res == 1)
378 return eap_tls_build_ack(reqDataLen, id, EAP_TYPE_TTLS,
379 data->ttls_version);
380 return req;
384 static u8 * eap_ttls_encrypt(struct eap_sm *sm, struct eap_ttls_data *data,
385 int id, u8 *plain, size_t plain_len,
386 size_t *out_len)
388 int res;
389 u8 *pos;
390 struct eap_hdr *req;
392 /* TODO: add support for fragmentation, if needed. This will need to
393 * add TLS Message Length field, if the frame is fragmented. */
394 req = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
395 if (req == NULL)
396 return NULL;
398 req->code = EAP_CODE_REQUEST;
399 req->identifier = id;
401 pos = (u8 *) (req + 1);
402 *pos++ = EAP_TYPE_TTLS;
403 *pos++ = data->ttls_version;
405 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
406 plain, plain_len,
407 pos, data->ssl.tls_out_limit);
408 if (res < 0) {
409 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 "
410 "data");
411 free(req);
412 return NULL;
415 *out_len = sizeof(struct eap_hdr) + 2 + res;
416 req->length = host_to_be16(*out_len);
417 return (u8 *) req;
421 static u8 * eap_ttls_build_phase2_eap_req(struct eap_sm *sm,
422 struct eap_ttls_data *data,
423 int id, size_t *reqDataLen)
425 u8 *req, *encr_req;
426 size_t req_len;
429 req = data->phase2_method->buildReq(sm, data->phase2_priv, id,
430 &req_len);
431 if (req == NULL)
432 return NULL;
434 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encapsulate Phase 2 data",
435 req, req_len);
437 if (eap_ttls_avp_encapsulate(&req, &req_len, RADIUS_ATTR_EAP_MESSAGE,
438 1) < 0) {
439 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate "
440 "packet");
441 return NULL;
444 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
445 "2 data", req, req_len);
447 encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen);
448 free(req);
450 return encr_req;
454 static u8 * eap_ttls_build_phase2_mschapv2(struct eap_sm *sm,
455 struct eap_ttls_data *data,
456 int id, size_t *reqDataLen)
458 u8 *req, *encr_req, *pos, *end;
459 size_t req_len;
460 int i;
462 pos = req = malloc(100);
463 if (req == NULL)
464 return NULL;
465 end = req + 200;
467 if (data->mschapv2_resp_ok) {
468 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS,
469 RADIUS_VENDOR_ID_MICROSOFT, 1, 43);
470 *pos++ = data->mschapv2_ident;
471 pos += snprintf((char *) pos, end - pos, "S=");
472 for (i = 0; i < sizeof(data->mschapv2_auth_response); i++) {
473 pos += snprintf((char *) pos, end - pos, "%02X",
474 data->mschapv2_auth_response[i]);
476 } else {
477 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR,
478 RADIUS_VENDOR_ID_MICROSOFT, 1, 6);
479 memcpy(pos, "Failed", 6);
480 pos += 6;
481 AVP_PAD(req, pos);
484 req_len = pos - req;
485 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
486 "data", req, req_len);
488 encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen);
489 free(req);
491 return encr_req;
495 static u8 * eap_ttls_buildReq(struct eap_sm *sm, void *priv, int id,
496 size_t *reqDataLen)
498 struct eap_ttls_data *data = priv;
500 switch (data->state) {
501 case START:
502 return eap_ttls_build_start(sm, data, id, reqDataLen);
503 case PHASE1:
504 return eap_ttls_build_req(sm, data, id, reqDataLen);
505 case PHASE2_METHOD:
506 return eap_ttls_build_phase2_eap_req(sm, data, id, reqDataLen);
507 case PHASE2_MSCHAPV2_RESP:
508 return eap_ttls_build_phase2_mschapv2(sm, data, id,
509 reqDataLen);
510 default:
511 wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
512 __func__, data->state);
513 return NULL;
518 static Boolean eap_ttls_check(struct eap_sm *sm, void *priv,
519 u8 *respData, size_t respDataLen)
521 struct eap_hdr *resp;
522 u8 *pos;
523 size_t len;
525 resp = (struct eap_hdr *) respData;
526 pos = (u8 *) (resp + 1);
527 if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_TTLS ||
528 (len = ntohs(resp->length)) > respDataLen) {
529 wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame");
530 return TRUE;
533 return FALSE;
537 static void eap_ttls_process_phase2_pap(struct eap_sm *sm,
538 struct eap_ttls_data *data,
539 const u8 *user_password,
540 size_t user_password_len)
542 /* TODO: add support for verifying that the user entry accepts
543 * EAP-TTLS/PAP. */
544 if (!sm->user || !sm->user->password) {
545 wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No user password "
546 "configured");
547 eap_ttls_state(data, FAILURE);
548 return;
551 if (sm->user->password_len != user_password_len ||
552 memcmp(sm->user->password, user_password, user_password_len) != 0)
554 wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password");
555 eap_ttls_state(data, FAILURE);
556 return;
559 wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password");
560 eap_ttls_state(data, SUCCESS);
564 static void eap_ttls_process_phase2_chap(struct eap_sm *sm,
565 struct eap_ttls_data *data,
566 const u8 *challenge,
567 size_t challenge_len,
568 const u8 *password,
569 size_t password_len)
571 u8 *chal, hash[MD5_MAC_LEN];
572 const u8 *addr[3];
573 size_t len[3];
575 if (challenge == NULL || password == NULL ||
576 challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN ||
577 password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) {
578 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes "
579 "(challenge len %lu password len %lu)",
580 (unsigned long) challenge_len,
581 (unsigned long) password_len);
582 eap_ttls_state(data, FAILURE);
583 return;
586 /* TODO: add support for verifying that the user entry accepts
587 * EAP-TTLS/CHAP. */
588 if (!sm->user || !sm->user->password) {
589 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No user password "
590 "configured");
591 eap_ttls_state(data, FAILURE);
592 return;
595 chal = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
596 EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
597 if (chal == NULL) {
598 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate "
599 "challenge from TLS data");
600 eap_ttls_state(data, FAILURE);
601 return;
604 if (memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 ||
605 password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) {
606 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch");
607 free(chal);
608 eap_ttls_state(data, FAILURE);
609 return;
611 free(chal);
613 /* MD5(Ident + Password + Challenge) */
614 addr[0] = password;
615 len[0] = 1;
616 addr[1] = sm->user->password;
617 len[1] = sm->user->password_len;
618 addr[2] = challenge;
619 len[2] = challenge_len;
620 md5_vector(3, addr, len, hash);
622 if (memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) {
623 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
624 eap_ttls_state(data, SUCCESS);
625 } else {
626 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password");
627 eap_ttls_state(data, FAILURE);
632 static void eap_ttls_process_phase2_mschap(struct eap_sm *sm,
633 struct eap_ttls_data *data,
634 u8 *challenge, size_t challenge_len,
635 u8 *response, size_t response_len)
637 u8 *chal, nt_response[24];
639 if (challenge == NULL || response == NULL ||
640 challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN ||
641 response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) {
642 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP "
643 "attributes (challenge len %lu response len %lu)",
644 (unsigned long) challenge_len,
645 (unsigned long) response_len);
646 eap_ttls_state(data, FAILURE);
647 return;
650 /* TODO: add support for verifying that the user entry accepts
651 * EAP-TTLS/MSCHAP. */
652 if (!sm->user || !sm->user->password) {
653 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password "
654 "configured");
655 eap_ttls_state(data, FAILURE);
656 return;
659 chal = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
660 EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
661 if (chal == NULL) {
662 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate "
663 "challenge from TLS data");
664 eap_ttls_state(data, FAILURE);
665 return;
668 if (memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 ||
669 response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
670 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch");
671 free(chal);
672 eap_ttls_state(data, FAILURE);
673 return;
675 free(chal);
677 nt_challenge_response(challenge, sm->user->password,
678 sm->user->password_len, nt_response);
680 if (memcmp(nt_response, response + 2 + 24, 24) == 0) {
681 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
682 eap_ttls_state(data, SUCCESS);
683 } else {
684 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response");
685 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received",
686 response + 2 + 24, 24);
687 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected",
688 nt_response, 24);
689 eap_ttls_state(data, FAILURE);
694 static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
695 struct eap_ttls_data *data,
696 u8 *challenge,
697 size_t challenge_len,
698 u8 *response, size_t response_len)
700 u8 *chal, *username, nt_response[24], *pos, *rx_resp, *peer_challenge,
701 *auth_challenge;
702 size_t username_len;
703 int i;
705 if (challenge == NULL || response == NULL ||
706 challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN ||
707 response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) {
708 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 "
709 "attributes (challenge len %lu response len %lu)",
710 (unsigned long) challenge_len,
711 (unsigned long) response_len);
712 eap_ttls_state(data, FAILURE);
713 return;
716 /* TODO: add support for verifying that the user entry accepts
717 * EAP-TTLS/MSCHAPV2. */
718 if (!sm->user || !sm->user->password) {
719 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password "
720 "configured");
721 eap_ttls_state(data, FAILURE);
722 return;
725 /* MSCHAPv2 does not include optional domain name in the
726 * challenge-response calculation, so remove domain prefix
727 * (if present). */
728 username = sm->identity;
729 username_len = sm->identity_len;
730 pos = username;
731 for (i = 0; i < username_len; i++) {
732 if (username[i] == '\\') {
733 username_len -= i + 1;
734 username += i + 1;
735 break;
739 chal = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
740 EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
741 if (chal == NULL) {
742 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate "
743 "challenge from TLS data");
744 eap_ttls_state(data, FAILURE);
745 return;
748 if (memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 ||
749 response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) {
750 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
751 free(chal);
752 eap_ttls_state(data, FAILURE);
753 return;
755 free(chal);
757 auth_challenge = challenge;
758 peer_challenge = response + 2;
760 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User",
761 username, username_len);
762 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge",
763 auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
764 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge",
765 peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
767 generate_nt_response(auth_challenge, peer_challenge,
768 username, username_len,
769 sm->user->password, sm->user->password_len,
770 nt_response);
772 rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
773 if (memcmp(nt_response, rx_resp, 24) == 0) {
774 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
775 "NT-Response");
776 data->mschapv2_resp_ok = 1;
778 generate_authenticator_response(sm->user->password,
779 sm->user->password_len,
780 peer_challenge,
781 auth_challenge,
782 username, username_len,
783 nt_response,
784 data->mschapv2_auth_response);
786 } else {
787 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid "
788 "NT-Response");
789 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received",
790 rx_resp, 24);
791 wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected",
792 nt_response, 24);
793 data->mschapv2_resp_ok = 0;
795 eap_ttls_state(data, PHASE2_MSCHAPV2_RESP);
796 data->mschapv2_ident = response[0];
800 static int eap_ttls_phase2_eap_init(struct eap_sm *sm,
801 struct eap_ttls_data *data, u8 eap_type)
803 if (data->phase2_priv && data->phase2_method) {
804 data->phase2_method->reset(sm, data->phase2_priv);
805 data->phase2_method = NULL;
806 data->phase2_priv = NULL;
808 data->phase2_method = eap_sm_get_eap_methods(eap_type);
809 if (!data->phase2_method)
810 return -1;
812 sm->init_phase2 = 1;
813 data->phase2_priv = data->phase2_method->init(sm);
814 sm->init_phase2 = 0;
815 return 0;
819 static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,
820 struct eap_ttls_data *data,
821 u8 *in_data, size_t in_len)
823 u8 next_type = EAP_TYPE_NONE;
824 struct eap_hdr *hdr;
825 u8 *pos;
826 size_t left;
828 if (data->phase2_priv == NULL) {
829 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not "
830 "initialized?!", __func__);
831 return;
834 hdr = (struct eap_hdr *) in_data;
835 pos = (u8 *) (hdr + 1);
836 left = in_len - sizeof(*hdr);
838 if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
839 wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; "
840 "allowed types", pos + 1, left - 1);
841 eap_sm_process_nak(sm, pos + 1, left - 1);
842 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
843 sm->user->methods[sm->user_eap_method_index] !=
844 EAP_TYPE_NONE) {
845 next_type =
846 sm->user->methods[sm->user_eap_method_index++];
847 wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d",
848 next_type);
849 eap_ttls_phase2_eap_init(sm, data, next_type);
850 } else {
851 eap_ttls_state(data, FAILURE);
853 return;
856 if (data->phase2_method->check(sm, data->phase2_priv, in_data,
857 in_len)) {
858 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to "
859 "ignore the packet");
860 return;
863 data->phase2_method->process(sm, data->phase2_priv, in_data, in_len);
865 if (!data->phase2_method->isDone(sm, data->phase2_priv))
866 return;
868 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
869 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed");
870 eap_ttls_state(data, FAILURE);
871 return;
874 switch (data->state) {
875 case PHASE2_START:
876 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
877 wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 "
878 "Identity not found in the user "
879 "database",
880 sm->identity, sm->identity_len);
881 eap_ttls_state(data, FAILURE);
882 break;
885 eap_ttls_state(data, PHASE2_METHOD);
886 next_type = sm->user->methods[0];
887 sm->user_eap_method_index = 1;
888 wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type);
889 break;
890 case PHASE2_METHOD:
891 eap_ttls_state(data, SUCCESS);
892 break;
893 case FAILURE:
894 break;
895 default:
896 wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
897 __func__, data->state);
898 break;
901 eap_ttls_phase2_eap_init(sm, data, next_type);
905 static void eap_ttls_process_phase2_eap(struct eap_sm *sm,
906 struct eap_ttls_data *data,
907 const u8 *eap, size_t eap_len)
909 struct eap_hdr *hdr;
910 size_t len;
912 if (data->state == PHASE2_START) {
913 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2");
914 if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0)
916 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "
917 "initialize EAP-Identity");
918 return;
922 if (eap_len < sizeof(*hdr)) {
923 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP "
924 "packet (len=%lu)", (unsigned long) eap_len);
925 return;
928 hdr = (struct eap_hdr *) eap;
929 len = be_to_host16(hdr->length);
930 wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "
931 "identifier=%d length=%lu", hdr->code, hdr->identifier,
932 (unsigned long) len);
933 if (len > eap_len) {
934 wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2"
935 " EAP frame (hdr len=%lu, data len in AVP=%lu)",
936 (unsigned long) len, (unsigned long) eap_len);
937 return;
940 switch (hdr->code) {
941 case EAP_CODE_RESPONSE:
942 eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr,
943 len);
944 break;
945 default:
946 wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in "
947 "Phase 2 EAP header", hdr->code);
948 break;
953 static void eap_ttls_process_phase2(struct eap_sm *sm,
954 struct eap_ttls_data *data,
955 struct eap_hdr *resp,
956 u8 *in_data, size_t in_len)
958 u8 *in_decrypted;
959 int buf_len, len_decrypted, res;
960 struct eap_ttls_avp parse;
962 wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
963 " Phase 2", (unsigned long) in_len);
965 res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len);
966 if (res < 0 || res == 1)
967 return;
969 buf_len = in_len;
970 if (data->ssl.tls_in_total > buf_len)
971 buf_len = data->ssl.tls_in_total;
972 in_decrypted = malloc(buf_len);
973 if (in_decrypted == NULL) {
974 free(data->ssl.tls_in);
975 data->ssl.tls_in = NULL;
976 data->ssl.tls_in_len = 0;
977 wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
978 "for decryption");
979 return;
982 len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
983 in_data, in_len,
984 in_decrypted, buf_len);
985 free(data->ssl.tls_in);
986 data->ssl.tls_in = NULL;
987 data->ssl.tls_in_len = 0;
988 if (len_decrypted < 0) {
989 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
990 "data");
991 free(in_decrypted);
992 eap_ttls_state(data, FAILURE);
993 return;
996 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
997 in_decrypted, len_decrypted);
999 if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) {
1000 wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
1001 free(in_decrypted);
1002 eap_ttls_state(data, FAILURE);
1003 return;
1006 if (parse.user_name) {
1007 free(sm->identity);
1008 sm->identity = malloc(parse.user_name_len);
1009 if (sm->identity) {
1010 memcpy(sm->identity, parse.user_name,
1011 parse.user_name_len);
1012 sm->identity_len = parse.user_name_len;
1014 if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1)
1015 != 0) {
1016 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not "
1017 "found in the user database");
1018 eap_ttls_state(data, FAILURE);
1019 goto done;
1023 if (parse.eap) {
1024 eap_ttls_process_phase2_eap(sm, data, parse.eap,
1025 parse.eap_len);
1026 } else if (parse.user_password) {
1027 eap_ttls_process_phase2_pap(sm, data, parse.user_password,
1028 parse.user_password_len);
1029 } else if (parse.chap_password) {
1030 eap_ttls_process_phase2_chap(sm, data,
1031 parse.chap_challenge,
1032 parse.chap_challenge_len,
1033 parse.chap_password,
1034 parse.chap_password_len);
1035 } else if (parse.mschap_response) {
1036 eap_ttls_process_phase2_mschap(sm, data,
1037 parse.mschap_challenge,
1038 parse.mschap_challenge_len,
1039 parse.mschap_response,
1040 parse.mschap_response_len);
1041 } else if (parse.mschap2_response) {
1042 eap_ttls_process_phase2_mschapv2(sm, data,
1043 parse.mschap_challenge,
1044 parse.mschap_challenge_len,
1045 parse.mschap2_response,
1046 parse.mschap2_response_len);
1049 done:
1050 free(in_decrypted);
1051 free(parse.eap);
1055 static void eap_ttls_process(struct eap_sm *sm, void *priv,
1056 u8 *respData, size_t respDataLen)
1058 struct eap_ttls_data *data = priv;
1059 struct eap_hdr *resp;
1060 u8 *pos, flags;
1061 int left;
1062 unsigned int tls_msg_len;
1063 int peer_version;
1065 resp = (struct eap_hdr *) respData;
1066 pos = (u8 *) (resp + 1);
1067 pos++;
1068 flags = *pos++;
1069 left = htons(resp->length) - sizeof(struct eap_hdr) - 2;
1070 wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "
1071 "Flags 0x%02x", (unsigned long) respDataLen, flags);
1072 peer_version = flags & EAP_PEAP_VERSION_MASK;
1073 if (peer_version < data->ttls_version) {
1074 wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
1075 "use version %d",
1076 peer_version, data->ttls_version, peer_version);
1077 data->ttls_version = peer_version;
1080 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
1081 if (left < 4) {
1082 wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS "
1083 "length");
1084 eap_ttls_state(data, FAILURE);
1085 return;
1087 tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) |
1088 pos[3];
1089 wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d",
1090 tls_msg_len);
1091 if (data->ssl.tls_in_left == 0) {
1092 data->ssl.tls_in_total = tls_msg_len;
1093 data->ssl.tls_in_left = tls_msg_len;
1094 free(data->ssl.tls_in);
1095 data->ssl.tls_in = NULL;
1096 data->ssl.tls_in_len = 0;
1098 pos += 4;
1099 left -= 4;
1102 switch (data->state) {
1103 case PHASE1:
1104 if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) {
1105 wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing "
1106 "failed");
1107 eap_ttls_state(data, FAILURE);
1109 break;
1110 case PHASE2_START:
1111 case PHASE2_METHOD:
1112 eap_ttls_process_phase2(sm, data, resp, pos, left);
1113 break;
1114 case PHASE2_MSCHAPV2_RESP:
1115 if (data->mschapv2_resp_ok && left == 0) {
1116 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
1117 "acknowledged response");
1118 eap_ttls_state(data, SUCCESS);
1119 } else if (!data->mschapv2_resp_ok) {
1120 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
1121 "acknowledged error");
1122 eap_ttls_state(data, FAILURE);
1123 } else {
1124 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
1125 "frame from peer (payload len %d, expected "
1126 "empty frame)", left);
1127 eap_ttls_state(data, FAILURE);
1129 break;
1130 default:
1131 wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",
1132 data->state, __func__);
1133 break;
1136 if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
1137 wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error "
1138 "in TLS processing");
1139 eap_ttls_state(data, FAILURE);
1144 static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv)
1146 struct eap_ttls_data *data = priv;
1147 return data->state == SUCCESS || data->state == FAILURE;
1151 static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
1153 struct eap_ttls_data *data = priv;
1154 u8 *eapKeyData;
1156 if (data->state != SUCCESS)
1157 return NULL;
1159 eapKeyData = eap_tls_derive_key(sm, &data->ssl,
1160 "ttls keying material",
1161 EAP_TLS_KEY_LEN);
1162 if (eapKeyData) {
1163 *len = EAP_TLS_KEY_LEN;
1164 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Derived key",
1165 eapKeyData, EAP_TLS_KEY_LEN);
1166 } else {
1167 wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
1170 return eapKeyData;
1174 static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv)
1176 struct eap_ttls_data *data = priv;
1177 return data->state == SUCCESS;
1181 const struct eap_method eap_method_ttls =
1183 .method = EAP_TYPE_TTLS,
1184 .name = "TTLS",
1185 .init = eap_ttls_init,
1186 .reset = eap_ttls_reset,
1187 .buildReq = eap_ttls_buildReq,
1188 .check = eap_ttls_check,
1189 .process = eap_ttls_process,
1190 .isDone = eap_ttls_isDone,
1191 .getKey = eap_ttls_getKey,
1192 .isSuccess = eap_ttls_isSuccess,