2 * EAP peer method: EAP-TTLS (RFC 5281)
3 * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/ms_funcs.h"
13 #include "crypto/sha1.h"
14 #include "crypto/tls.h"
15 #include "eap_common/chap.h"
16 #include "eap_common/eap_ttls.h"
19 #include "eap_tls_common.h"
20 #include "eap_config.h"
23 #define EAP_TTLS_VERSION 0
26 static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
29 struct eap_ttls_data {
30 struct eap_ssl_data ssl;
34 const struct eap_method *phase2_method;
41 EAP_TTLS_PHASE2_MSCHAPV2,
42 EAP_TTLS_PHASE2_MSCHAP,
46 struct eap_method_type phase2_eap_type;
47 struct eap_method_type *phase2_eap_types;
48 size_t num_phase2_eap_types;
50 u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];
51 int auth_response_valid;
52 u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */
54 int resuming; /* starting a resumed session */
55 int reauth; /* reauthentication */
60 struct wpabuf *pending_phase2_req;
69 static void * eap_ttls_init(struct eap_sm *sm)
71 struct eap_ttls_data *data;
72 struct eap_peer_config *config = eap_get_config(sm);
75 data = os_zalloc(sizeof(*data));
78 data->ttls_version = EAP_TTLS_VERSION;
80 data->phase2_type = EAP_TTLS_PHASE2_EAP;
82 if (config && config->phase2) {
83 if (os_strstr(config->phase2, "autheap=")) {
85 data->phase2_type = EAP_TTLS_PHASE2_EAP;
86 } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
87 selected = "MSCHAPV2";
88 data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
89 } else if (os_strstr(config->phase2, "auth=MSCHAP")) {
91 data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
92 } else if (os_strstr(config->phase2, "auth=PAP")) {
94 data->phase2_type = EAP_TTLS_PHASE2_PAP;
95 } else if (os_strstr(config->phase2, "auth=CHAP")) {
97 data->phase2_type = EAP_TTLS_PHASE2_CHAP;
100 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
102 if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
103 if (eap_peer_select_phase2_methods(config, "autheap=",
104 &data->phase2_eap_types,
105 &data->num_phase2_eap_types)
107 eap_ttls_deinit(sm, data);
111 data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
112 data->phase2_eap_type.method = EAP_TYPE_NONE;
115 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TTLS)) {
116 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
117 eap_ttls_deinit(sm, data);
125 static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
126 struct eap_ttls_data *data)
128 if (data->phase2_priv && data->phase2_method) {
129 data->phase2_method->deinit(sm, data->phase2_priv);
130 data->phase2_method = NULL;
131 data->phase2_priv = NULL;
136 static void eap_ttls_free_key(struct eap_ttls_data *data)
138 if (data->key_data) {
139 bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
140 data->key_data = NULL;
145 static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
147 struct eap_ttls_data *data = priv;
150 eap_ttls_phase2_eap_deinit(sm, data);
151 os_free(data->phase2_eap_types);
152 eap_peer_tls_ssl_deinit(sm, &data->ssl);
153 eap_ttls_free_key(data);
154 os_free(data->session_id);
155 wpabuf_free(data->pending_phase2_req);
160 static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
161 int mandatory, size_t len)
163 struct ttls_avp_vendor *avp;
167 avp = (struct ttls_avp_vendor *) avphdr;
168 flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
170 flags |= AVP_FLAGS_VENDOR;
171 hdrlen = sizeof(*avp);
172 avp->vendor_id = host_to_be32(vendor_id);
174 hdrlen = sizeof(struct ttls_avp);
177 avp->avp_code = host_to_be32(avp_code);
178 avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len));
180 return avphdr + hdrlen;
184 static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
185 u32 vendor_id, int mandatory,
186 const u8 *data, size_t len)
189 pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
190 os_memcpy(pos, data, len);
197 static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
203 msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
210 avp = wpabuf_mhead(msg);
211 pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp));
212 os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
213 pos += wpabuf_len(*resp);
216 wpabuf_put(msg, pos - avp);
222 static int eap_ttls_v0_derive_key(struct eap_sm *sm,
223 struct eap_ttls_data *data)
225 eap_ttls_free_key(data);
226 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
227 "ttls keying material",
230 if (!data->key_data) {
231 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");
235 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
236 data->key_data, EAP_TLS_KEY_LEN);
237 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived EMSK",
238 data->key_data + EAP_TLS_KEY_LEN,
241 os_free(data->session_id);
242 data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
245 if (data->session_id) {
246 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Derived Session-Id",
247 data->session_id, data->id_len);
249 wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive Session-Id");
256 static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
257 struct eap_ttls_data *data, size_t len)
259 return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
263 static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
267 for (i = 0; i < data->num_phase2_eap_types; i++) {
268 if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
269 data->phase2_eap_types[i].method != method)
272 data->phase2_eap_type.vendor =
273 data->phase2_eap_types[i].vendor;
274 data->phase2_eap_type.method =
275 data->phase2_eap_types[i].method;
276 wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
277 "Phase 2 EAP vendor %d method %d",
278 data->phase2_eap_type.vendor,
279 data->phase2_eap_type.method);
285 static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
286 struct eap_ttls_data *data,
287 struct eap_method_ret *ret,
288 struct eap_hdr *hdr, size_t len,
289 struct wpabuf **resp)
292 struct eap_method_ret iret;
294 os_memset(&iret, 0, sizeof(iret));
295 wpabuf_set(&msg, hdr, len);
296 *resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
298 if ((iret.methodState == METHOD_DONE ||
299 iret.methodState == METHOD_MAY_CONT) &&
300 (iret.decision == DECISION_UNCOND_SUCC ||
301 iret.decision == DECISION_COND_SUCC ||
302 iret.decision == DECISION_FAIL)) {
303 ret->methodState = iret.methodState;
304 ret->decision = iret.decision;
311 static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
312 struct eap_ttls_data *data,
313 struct eap_method_ret *ret,
314 struct eap_hdr *hdr, size_t len,
315 u8 method, struct wpabuf **resp)
318 if (data->tnc_started && data->phase2_method &&
319 data->phase2_priv && method == EAP_TYPE_TNC &&
320 data->phase2_eap_type.method == EAP_TYPE_TNC)
321 return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
324 if (data->ready_for_tnc && !data->tnc_started &&
325 method == EAP_TYPE_TNC) {
326 wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
328 data->tnc_started = 1;
331 if (data->tnc_started) {
332 if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF ||
333 data->phase2_eap_type.method == EAP_TYPE_TNC) {
334 wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP "
335 "type %d for TNC", method);
339 data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
340 data->phase2_eap_type.method = method;
341 wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
342 "Phase 2 EAP vendor %d method %d (TNC)",
343 data->phase2_eap_type.vendor,
344 data->phase2_eap_type.method);
346 if (data->phase2_type == EAP_TTLS_PHASE2_EAP)
347 eap_ttls_phase2_eap_deinit(sm, data);
351 if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
352 data->phase2_eap_type.method == EAP_TYPE_NONE)
353 eap_ttls_phase2_select_eap_method(data, method);
355 if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
357 if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
358 data->num_phase2_eap_types,
364 if (data->phase2_priv == NULL) {
365 data->phase2_method = eap_peer_get_eap_method(
366 EAP_VENDOR_IETF, method);
367 if (data->phase2_method) {
369 data->phase2_priv = data->phase2_method->init(sm);
373 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
374 wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
375 "Phase 2 EAP method %d", method);
379 return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp);
383 static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
384 struct eap_ttls_data *data,
385 struct eap_method_ret *ret,
387 struct wpabuf **resp)
389 size_t len = be_to_host16(hdr->length);
391 struct eap_peer_config *config = eap_get_config(sm);
393 if (len <= sizeof(struct eap_hdr)) {
394 wpa_printf(MSG_INFO, "EAP-TTLS: too short "
395 "Phase 2 request (len=%lu)", (unsigned long) len);
398 pos = (u8 *) (hdr + 1);
399 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
401 case EAP_TYPE_IDENTITY:
402 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
405 if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
412 (config->pending_req_identity || config->pending_req_password ||
413 config->pending_req_otp)) {
420 wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
422 return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1);
426 static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
427 struct eap_ttls_data *data,
428 struct eap_method_ret *ret,
429 struct wpabuf **resp)
433 u8 *buf, *pos, *challenge, *peer_challenge;
434 const u8 *identity, *password;
435 size_t identity_len, password_len;
438 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
440 identity = eap_get_config_identity(sm, &identity_len);
441 password = eap_get_config_password2(sm, &password_len, &pwhash);
442 if (identity == NULL || password == NULL)
445 msg = wpabuf_alloc(identity_len + 1000);
447 wpa_printf(MSG_ERROR,
448 "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
451 pos = buf = wpabuf_mhead(msg);
454 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
455 identity, identity_len);
457 /* MS-CHAP-Challenge */
458 challenge = eap_ttls_implicit_challenge(
459 sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
460 if (challenge == NULL) {
462 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
463 "implicit challenge");
467 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
468 RADIUS_VENDOR_ID_MICROSOFT, 1,
469 challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
471 /* MS-CHAP2-Response */
472 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,
473 RADIUS_VENDOR_ID_MICROSOFT, 1,
474 EAP_TTLS_MSCHAPV2_RESPONSE_LEN);
475 data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
476 *pos++ = data->ident;
477 *pos++ = 0; /* Flags */
478 if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
481 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
482 "random data for peer challenge");
485 peer_challenge = pos;
486 pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
487 os_memset(pos, 0, 8); /* Reserved, must be zero */
489 if (mschapv2_derive_response(identity, identity_len, password,
490 password_len, pwhash, challenge,
491 peer_challenge, pos, data->auth_response,
495 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
499 data->auth_response_valid = 1;
505 wpabuf_put(msg, pos - buf);
509 #else /* EAP_MSCHAPv2 */
510 wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
512 #endif /* EAP_MSCHAPv2 */
516 static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
517 struct eap_ttls_data *data,
518 struct eap_method_ret *ret,
519 struct wpabuf **resp)
522 u8 *buf, *pos, *challenge;
523 const u8 *identity, *password;
524 size_t identity_len, password_len;
527 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
529 identity = eap_get_config_identity(sm, &identity_len);
530 password = eap_get_config_password2(sm, &password_len, &pwhash);
531 if (identity == NULL || password == NULL)
534 msg = wpabuf_alloc(identity_len + 1000);
536 wpa_printf(MSG_ERROR,
537 "EAP-TTLS/MSCHAP: Failed to allocate memory");
540 pos = buf = wpabuf_mhead(msg);
543 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
544 identity, identity_len);
546 /* MS-CHAP-Challenge */
547 challenge = eap_ttls_implicit_challenge(
548 sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
549 if (challenge == NULL) {
551 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
552 "implicit challenge");
556 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
557 RADIUS_VENDOR_ID_MICROSOFT, 1,
558 challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
560 /* MS-CHAP-Response */
561 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,
562 RADIUS_VENDOR_ID_MICROSOFT, 1,
563 EAP_TTLS_MSCHAP_RESPONSE_LEN);
564 data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
565 *pos++ = data->ident;
566 *pos++ = 1; /* Flags: Use NT style passwords */
567 os_memset(pos, 0, 24); /* LM-Response */
570 challenge_response(challenge, password, pos); /* NT-Response */
571 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
574 nt_challenge_response(challenge, password, password_len,
575 pos); /* NT-Response */
576 wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
577 password, password_len);
579 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
580 challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
581 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
586 wpabuf_put(msg, pos - buf);
589 /* EAP-TTLS/MSCHAP does not provide tunneled success
590 * notification, so assume that Phase2 succeeds. */
591 ret->methodState = METHOD_DONE;
592 ret->decision = DECISION_COND_SUCC;
598 static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
599 struct eap_ttls_data *data,
600 struct eap_method_ret *ret,
601 struct wpabuf **resp)
606 const u8 *identity, *password;
607 size_t identity_len, password_len;
609 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
611 identity = eap_get_config_identity(sm, &identity_len);
612 password = eap_get_config_password(sm, &password_len);
613 if (identity == NULL || password == NULL)
616 msg = wpabuf_alloc(identity_len + password_len + 100);
618 wpa_printf(MSG_ERROR,
619 "EAP-TTLS/PAP: Failed to allocate memory");
622 pos = buf = wpabuf_mhead(msg);
625 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
626 identity, identity_len);
628 /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
629 * the data, so no separate encryption is used in the AVP itself.
630 * However, the password is padded to obfuscate its length. */
631 pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15;
632 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
634 os_memcpy(pos, password, password_len);
636 os_memset(pos, 0, pad);
640 wpabuf_put(msg, pos - buf);
643 /* EAP-TTLS/PAP does not provide tunneled success notification,
644 * so assume that Phase2 succeeds. */
645 ret->methodState = METHOD_DONE;
646 ret->decision = DECISION_COND_SUCC;
652 static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
653 struct eap_ttls_data *data,
654 struct eap_method_ret *ret,
655 struct wpabuf **resp)
658 u8 *buf, *pos, *challenge;
659 const u8 *identity, *password;
660 size_t identity_len, password_len;
662 wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
664 identity = eap_get_config_identity(sm, &identity_len);
665 password = eap_get_config_password(sm, &password_len);
666 if (identity == NULL || password == NULL)
669 msg = wpabuf_alloc(identity_len + 1000);
671 wpa_printf(MSG_ERROR,
672 "EAP-TTLS/CHAP: Failed to allocate memory");
675 pos = buf = wpabuf_mhead(msg);
678 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
679 identity, identity_len);
682 challenge = eap_ttls_implicit_challenge(
683 sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
684 if (challenge == NULL) {
686 wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
687 "implicit challenge");
691 pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
692 challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
695 pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
696 1 + EAP_TTLS_CHAP_PASSWORD_LEN);
697 data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
698 *pos++ = data->ident;
700 /* MD5(Ident + Password + Challenge) */
701 chap_md5(data->ident, password, password_len, challenge,
702 EAP_TTLS_CHAP_CHALLENGE_LEN, pos);
704 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
705 identity, identity_len);
706 wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
707 password, password_len);
708 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
709 challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
710 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
711 pos, EAP_TTLS_CHAP_PASSWORD_LEN);
712 pos += EAP_TTLS_CHAP_PASSWORD_LEN;
716 wpabuf_put(msg, pos - buf);
719 /* EAP-TTLS/CHAP does not provide tunneled success
720 * notification, so assume that Phase2 succeeds. */
721 ret->methodState = METHOD_DONE;
722 ret->decision = DECISION_COND_SUCC;
728 static int eap_ttls_phase2_request(struct eap_sm *sm,
729 struct eap_ttls_data *data,
730 struct eap_method_ret *ret,
732 struct wpabuf **resp)
736 enum phase2_types phase2_type = data->phase2_type;
739 if (data->tnc_started) {
740 wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC");
741 phase2_type = EAP_TTLS_PHASE2_EAP;
745 if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
746 phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
747 phase2_type == EAP_TTLS_PHASE2_PAP ||
748 phase2_type == EAP_TTLS_PHASE2_CHAP) {
749 if (eap_get_config_identity(sm, &len) == NULL) {
751 "EAP-TTLS: Identity not configured");
752 eap_sm_request_identity(sm);
753 if (eap_get_config_password(sm, &len) == NULL)
754 eap_sm_request_password(sm);
758 if (eap_get_config_password(sm, &len) == NULL) {
760 "EAP-TTLS: Password not configured");
761 eap_sm_request_password(sm);
766 switch (phase2_type) {
767 case EAP_TTLS_PHASE2_EAP:
768 res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp);
770 case EAP_TTLS_PHASE2_MSCHAPV2:
771 res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp);
773 case EAP_TTLS_PHASE2_MSCHAP:
774 res = eap_ttls_phase2_request_mschap(sm, data, ret, resp);
776 case EAP_TTLS_PHASE2_PAP:
777 res = eap_ttls_phase2_request_pap(sm, data, ret, resp);
779 case EAP_TTLS_PHASE2_CHAP:
780 res = eap_ttls_phase2_request_chap(sm, data, ret, resp);
783 wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
789 ret->methodState = METHOD_DONE;
790 ret->decision = DECISION_FAIL;
797 struct ttls_parse_avp {
805 static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen,
806 struct ttls_parse_avp *parse)
808 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
809 if (parse->eapdata == NULL) {
810 parse->eapdata = os_malloc(dlen);
811 if (parse->eapdata == NULL) {
812 wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
813 "memory for Phase 2 EAP data");
816 os_memcpy(parse->eapdata, dpos, dlen);
817 parse->eap_len = dlen;
819 u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen);
820 if (neweap == NULL) {
821 wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
822 "memory for Phase 2 EAP data");
825 os_memcpy(neweap + parse->eap_len, dpos, dlen);
826 parse->eapdata = neweap;
827 parse->eap_len += dlen;
834 static int eap_ttls_parse_avp(u8 *pos, size_t left,
835 struct ttls_parse_avp *parse)
837 struct ttls_avp *avp;
838 u32 avp_code, avp_length, vendor_id = 0;
842 avp = (struct ttls_avp *) pos;
843 avp_code = be_to_host32(avp->avp_code);
844 avp_length = be_to_host32(avp->avp_length);
845 avp_flags = (avp_length >> 24) & 0xff;
846 avp_length &= 0xffffff;
847 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
848 "length=%d", (int) avp_code, avp_flags,
851 if (avp_length > left) {
852 wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
853 "(len=%d, left=%lu) - dropped",
854 (int) avp_length, (unsigned long) left);
858 if (avp_length < sizeof(*avp)) {
859 wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d",
864 dpos = (u8 *) (avp + 1);
865 dlen = avp_length - sizeof(*avp);
866 if (avp_flags & AVP_FLAGS_VENDOR) {
868 wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP "
872 vendor_id = WPA_GET_BE32(dpos);
873 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
879 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
881 if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
882 if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0)
884 } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) {
885 /* This is an optional message that can be displayed to
887 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message",
889 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
890 avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {
891 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success",
894 wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "
895 "MS-CHAP2-Success length "
896 "(len=%lu, expected 43)",
897 (unsigned long) dlen);
900 parse->mschapv2 = dpos;
901 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
902 avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {
903 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error",
905 parse->mschapv2_error = 1;
906 } else if (avp_flags & AVP_FLAGS_MANDATORY) {
907 wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP "
908 "code %d vendor_id %d - dropped",
909 (int) avp_code, (int) vendor_id);
912 wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP "
913 "code %d vendor_id %d",
914 (int) avp_code, (int) vendor_id);
921 static int eap_ttls_parse_avps(struct wpabuf *in_decrypted,
922 struct ttls_parse_avp *parse)
928 pos = wpabuf_mhead(in_decrypted);
929 left = wpabuf_len(in_decrypted);
930 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left);
931 if (left < sizeof(struct ttls_avp)) {
932 wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
933 " len=%lu expected %lu or more - dropped",
934 (unsigned long) left,
935 (unsigned long) sizeof(struct ttls_avp));
940 os_memset(parse, 0, sizeof(*parse));
943 avp_length = eap_ttls_parse_avp(pos, left, parse);
947 pad = (4 - (avp_length & 3)) & 3;
948 pos += avp_length + pad;
949 if (left < avp_length + pad)
952 left -= avp_length + pad;
959 static u8 * eap_ttls_fake_identity_request(void)
964 wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
965 "Phase 2 - use fake EAP-Request Identity");
966 buf = os_malloc(sizeof(*hdr) + 1);
968 wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
969 "memory for fake EAP-Identity Request");
973 hdr = (struct eap_hdr *) buf;
974 hdr->code = EAP_CODE_REQUEST;
976 hdr->length = host_to_be16(sizeof(*hdr) + 1);
977 buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY;
983 static int eap_ttls_encrypt_response(struct eap_sm *sm,
984 struct eap_ttls_data *data,
985 struct wpabuf *resp, u8 identifier,
986 struct wpabuf **out_data)
991 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data",
993 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
994 data->ttls_version, identifier,
996 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
1007 static int eap_ttls_process_phase2_eap(struct eap_sm *sm,
1008 struct eap_ttls_data *data,
1009 struct eap_method_ret *ret,
1010 struct ttls_parse_avp *parse,
1011 struct wpabuf **resp)
1013 struct eap_hdr *hdr;
1016 if (parse->eapdata == NULL) {
1017 wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the "
1018 "packet - dropped");
1022 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP",
1023 parse->eapdata, parse->eap_len);
1024 hdr = (struct eap_hdr *) parse->eapdata;
1026 if (parse->eap_len < sizeof(*hdr)) {
1027 wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP "
1028 "frame (len=%lu, expected %lu or more) - dropped",
1029 (unsigned long) parse->eap_len,
1030 (unsigned long) sizeof(*hdr));
1033 len = be_to_host16(hdr->length);
1034 if (len > parse->eap_len) {
1035 wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 "
1036 "EAP frame (EAP hdr len=%lu, EAP data len in "
1038 (unsigned long) len,
1039 (unsigned long) parse->eap_len);
1042 wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
1043 "identifier=%d length=%lu",
1044 hdr->code, hdr->identifier, (unsigned long) len);
1045 switch (hdr->code) {
1046 case EAP_CODE_REQUEST:
1047 if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) {
1048 wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1049 "processing failed");
1054 wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in "
1055 "Phase 2 EAP header", hdr->code);
1063 static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
1064 struct eap_ttls_data *data,
1065 struct eap_method_ret *ret,
1066 struct ttls_parse_avp *parse)
1069 if (parse->mschapv2_error) {
1070 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
1071 "MS-CHAP-Error - failed");
1072 ret->methodState = METHOD_DONE;
1073 ret->decision = DECISION_FAIL;
1074 /* Reply with empty data to ACK error */
1078 if (parse->mschapv2 == NULL) {
1080 if (data->phase2_success && parse->eapdata) {
1082 * Allow EAP-TNC to be started after successfully
1083 * completed MSCHAPV2.
1087 #endif /* EAP_TNC */
1088 wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP "
1089 "received for Phase2 MSCHAPV2");
1092 if (parse->mschapv2[0] != data->ident) {
1093 wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 "
1094 "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)",
1095 parse->mschapv2[0], data->ident);
1098 if (!data->auth_response_valid ||
1099 mschapv2_verify_auth_response(data->auth_response,
1100 parse->mschapv2 + 1, 42)) {
1101 wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator "
1102 "response in Phase 2 MSCHAPV2 success request");
1106 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
1107 "authentication succeeded");
1108 ret->methodState = METHOD_DONE;
1109 ret->decision = DECISION_UNCOND_SUCC;
1110 data->phase2_success = 1;
1113 * Reply with empty data; authentication server will reply
1114 * with EAP-Success after this.
1117 #else /* EAP_MSCHAPv2 */
1118 wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
1120 #endif /* EAP_MSCHAPv2 */
1125 static int eap_ttls_process_tnc_start(struct eap_sm *sm,
1126 struct eap_ttls_data *data,
1127 struct eap_method_ret *ret,
1128 struct ttls_parse_avp *parse,
1129 struct wpabuf **resp)
1131 /* TNC uses inner EAP method after non-EAP TTLS phase 2. */
1132 if (parse->eapdata == NULL) {
1133 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1134 "unexpected tunneled data (no EAP)");
1138 if (!data->ready_for_tnc) {
1139 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1140 "EAP after non-EAP, but not ready for TNC");
1144 wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
1146 data->tnc_started = 1;
1148 if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0)
1153 #endif /* EAP_TNC */
1156 static int eap_ttls_process_decrypted(struct eap_sm *sm,
1157 struct eap_ttls_data *data,
1158 struct eap_method_ret *ret,
1160 struct ttls_parse_avp *parse,
1161 struct wpabuf *in_decrypted,
1162 struct wpabuf **out_data)
1164 struct wpabuf *resp = NULL;
1165 struct eap_peer_config *config = eap_get_config(sm);
1167 enum phase2_types phase2_type = data->phase2_type;
1170 if (data->tnc_started)
1171 phase2_type = EAP_TTLS_PHASE2_EAP;
1172 #endif /* EAP_TNC */
1174 switch (phase2_type) {
1175 case EAP_TTLS_PHASE2_EAP:
1176 if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) <
1180 case EAP_TTLS_PHASE2_MSCHAPV2:
1181 res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse);
1183 if (res == 1 && parse->eapdata && data->phase2_success) {
1185 * TNC may be required as the next
1186 * authentication method within the tunnel.
1188 ret->methodState = METHOD_MAY_CONT;
1189 data->ready_for_tnc = 1;
1190 if (eap_ttls_process_tnc_start(sm, data, ret, parse,
1194 #endif /* EAP_TNC */
1196 case EAP_TTLS_PHASE2_MSCHAP:
1197 case EAP_TTLS_PHASE2_PAP:
1198 case EAP_TTLS_PHASE2_CHAP:
1200 if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) <
1205 /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled
1206 * requests to the supplicant */
1207 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected "
1210 #endif /* EAP_TNC */
1214 if (eap_ttls_encrypt_response(sm, data, resp, identifier,
1217 } else if (config->pending_req_identity ||
1218 config->pending_req_password ||
1219 config->pending_req_otp ||
1220 config->pending_req_new_password) {
1221 wpabuf_free(data->pending_phase2_req);
1222 data->pending_phase2_req = wpabuf_dup(in_decrypted);
1229 static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
1230 struct eap_ttls_data *data,
1231 struct eap_method_ret *ret,
1233 struct wpabuf **out_data)
1236 struct eap_hdr *hdr;
1237 struct wpabuf *resp;
1239 hdr = (struct eap_hdr *) eap_ttls_fake_identity_request();
1241 ret->methodState = METHOD_DONE;
1242 ret->decision = DECISION_FAIL;
1247 if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) {
1248 wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1249 "processing failed");
1252 struct eap_peer_config *config = eap_get_config(sm);
1254 (config->pending_req_identity ||
1255 config->pending_req_password ||
1256 config->pending_req_otp ||
1257 config->pending_req_new_password)) {
1259 * Use empty buffer to force implicit request
1260 * processing when EAP request is re-processed after
1263 wpabuf_free(data->pending_phase2_req);
1264 data->pending_phase2_req = wpabuf_alloc(0);
1267 retval = eap_ttls_encrypt_response(sm, data, resp, identifier,
1274 ret->methodState = METHOD_DONE;
1275 ret->decision = DECISION_FAIL;
1282 static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data,
1283 struct eap_method_ret *ret, u8 identifier,
1284 struct wpabuf **out_data)
1286 data->phase2_start = 0;
1289 * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only
1290 * if TLS part was indeed resuming a previous session. Most
1291 * Authentication Servers terminate EAP-TTLS before reaching this
1292 * point, but some do not. Make wpa_supplicant stop phase 2 here, if
1296 tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
1297 wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "
1299 *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS,
1300 data->ttls_version);
1301 ret->methodState = METHOD_DONE;
1302 ret->decision = DECISION_UNCOND_SUCC;
1303 data->phase2_success = 1;
1307 return eap_ttls_implicit_identity_request(sm, data, ret, identifier,
1312 static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
1313 struct eap_method_ret *ret, u8 identifier,
1314 const struct wpabuf *in_data,
1315 struct wpabuf **out_data)
1317 struct wpabuf *in_decrypted = NULL;
1319 struct ttls_parse_avp parse;
1321 os_memset(&parse, 0, sizeof(parse));
1323 wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
1325 in_data ? (unsigned long) wpabuf_len(in_data) : 0);
1327 if (data->pending_phase2_req) {
1328 wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
1329 "skip decryption and use old data");
1330 /* Clear TLS reassembly state. */
1331 eap_peer_tls_reset_input(&data->ssl);
1333 in_decrypted = data->pending_phase2_req;
1334 data->pending_phase2_req = NULL;
1335 if (wpabuf_len(in_decrypted) == 0) {
1336 wpabuf_free(in_decrypted);
1337 return eap_ttls_implicit_identity_request(
1338 sm, data, ret, identifier, out_data);
1343 if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
1344 data->phase2_start) {
1345 return eap_ttls_phase2_start(sm, data, ret, identifier,
1349 if (in_data == NULL || wpabuf_len(in_data) == 0) {
1350 /* Received TLS ACK - requesting more fragments */
1351 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
1353 identifier, NULL, out_data);
1356 retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
1361 data->phase2_start = 0;
1363 if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) {
1368 retval = eap_ttls_process_decrypted(sm, data, ret, identifier,
1369 &parse, in_decrypted, out_data);
1372 wpabuf_free(in_decrypted);
1373 os_free(parse.eapdata);
1376 ret->methodState = METHOD_DONE;
1377 ret->decision = DECISION_FAIL;
1384 static int eap_ttls_process_handshake(struct eap_sm *sm,
1385 struct eap_ttls_data *data,
1386 struct eap_method_ret *ret,
1388 const u8 *in_data, size_t in_len,
1389 struct wpabuf **out_data)
1393 res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
1394 data->ttls_version, identifier,
1395 in_data, in_len, out_data);
1397 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1398 wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
1400 if (data->resuming) {
1401 wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may "
1403 ret->decision = DECISION_COND_SUCC;
1404 ret->methodState = METHOD_MAY_CONT;
1406 data->phase2_start = 1;
1407 eap_ttls_v0_derive_key(sm, data);
1409 if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
1410 if (eap_ttls_decrypt(sm, data, ret, identifier,
1412 wpa_printf(MSG_WARNING, "EAP-TTLS: "
1413 "failed to process early "
1414 "start for Phase 2");
1424 * Application data included in the handshake message.
1426 wpabuf_free(data->pending_phase2_req);
1427 data->pending_phase2_req = *out_data;
1429 wpabuf_set(&msg, in_data, in_len);
1430 res = eap_ttls_decrypt(sm, data, ret, identifier, &msg,
1438 static void eap_ttls_check_auth_status(struct eap_sm *sm,
1439 struct eap_ttls_data *data,
1440 struct eap_method_ret *ret)
1442 if (ret->methodState == METHOD_DONE) {
1443 ret->allowNotifications = FALSE;
1444 if (ret->decision == DECISION_UNCOND_SUCC ||
1445 ret->decision == DECISION_COND_SUCC) {
1446 wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1447 "completed successfully");
1448 data->phase2_success = 1;
1450 if (!data->ready_for_tnc && !data->tnc_started) {
1452 * TNC may be required as the next
1453 * authentication method within the tunnel.
1455 ret->methodState = METHOD_MAY_CONT;
1456 data->ready_for_tnc = 1;
1458 #endif /* EAP_TNC */
1460 } else if (ret->methodState == METHOD_MAY_CONT &&
1461 (ret->decision == DECISION_UNCOND_SUCC ||
1462 ret->decision == DECISION_COND_SUCC)) {
1463 wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1464 "completed successfully (MAY_CONT)");
1465 data->phase2_success = 1;
1470 static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
1471 struct eap_method_ret *ret,
1472 const struct wpabuf *reqData)
1477 struct wpabuf *resp;
1479 struct eap_ttls_data *data = priv;
1481 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
1482 reqData, &left, &flags);
1485 id = eap_get_id(reqData);
1487 if (flags & EAP_TLS_FLAGS_START) {
1488 wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
1489 "ver=%d)", flags & EAP_TLS_VERSION_MASK,
1490 data->ttls_version);
1492 /* RFC 5281, Ch. 9.2:
1493 * "This packet MAY contain additional information in the form
1494 * of AVPs, which may provide useful hints to the client"
1495 * For now, ignore any potential extra data.
1501 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1504 wpabuf_set(&msg, pos, left);
1505 res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp);
1507 res = eap_ttls_process_handshake(sm, data, ret, id,
1511 eap_ttls_check_auth_status(sm, data, ret);
1513 /* FIX: what about res == -1? Could just move all error processing into
1514 * the other functions and get rid of this res==1 case here. */
1517 return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
1518 data->ttls_version);
1524 static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
1526 struct eap_ttls_data *data = priv;
1527 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1528 data->phase2_success;
1532 static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
1534 struct eap_ttls_data *data = priv;
1535 wpabuf_free(data->pending_phase2_req);
1536 data->pending_phase2_req = NULL;
1538 data->ready_for_tnc = 0;
1539 data->tnc_started = 0;
1540 #endif /* EAP_TNC */
1544 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
1546 struct eap_ttls_data *data = priv;
1547 eap_ttls_free_key(data);
1548 os_free(data->session_id);
1549 data->session_id = NULL;
1550 if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1554 if (data->phase2_priv && data->phase2_method &&
1555 data->phase2_method->init_for_reauth)
1556 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1557 data->phase2_start = 0;
1558 data->phase2_success = 0;
1565 static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf,
1566 size_t buflen, int verbose)
1568 struct eap_ttls_data *data = priv;
1571 len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1572 ret = os_snprintf(buf + len, buflen - len,
1573 "EAP-TTLSv%d Phase2 method=",
1574 data->ttls_version);
1575 if (os_snprintf_error(buflen - len, ret))
1578 switch (data->phase2_type) {
1579 case EAP_TTLS_PHASE2_EAP:
1580 ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n",
1581 data->phase2_method ?
1582 data->phase2_method->name : "?");
1584 case EAP_TTLS_PHASE2_MSCHAPV2:
1585 ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n");
1587 case EAP_TTLS_PHASE2_MSCHAP:
1588 ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n");
1590 case EAP_TTLS_PHASE2_PAP:
1591 ret = os_snprintf(buf + len, buflen - len, "PAP\n");
1593 case EAP_TTLS_PHASE2_CHAP:
1594 ret = os_snprintf(buf + len, buflen - len, "CHAP\n");
1600 if (os_snprintf_error(buflen - len, ret))
1608 static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv)
1610 struct eap_ttls_data *data = priv;
1611 return data->key_data != NULL && data->phase2_success;
1615 static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
1617 struct eap_ttls_data *data = priv;
1620 if (data->key_data == NULL || !data->phase2_success)
1623 key = os_malloc(EAP_TLS_KEY_LEN);
1627 *len = EAP_TLS_KEY_LEN;
1628 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1634 static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1636 struct eap_ttls_data *data = priv;
1639 if (data->session_id == NULL || !data->phase2_success)
1642 id = os_malloc(data->id_len);
1646 *len = data->id_len;
1647 os_memcpy(id, data->session_id, data->id_len);
1653 static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1655 struct eap_ttls_data *data = priv;
1658 if (data->key_data == NULL)
1661 key = os_malloc(EAP_EMSK_LEN);
1665 *len = EAP_EMSK_LEN;
1666 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
1672 int eap_peer_ttls_register(void)
1674 struct eap_method *eap;
1677 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1678 EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
1682 eap->init = eap_ttls_init;
1683 eap->deinit = eap_ttls_deinit;
1684 eap->process = eap_ttls_process;
1685 eap->isKeyAvailable = eap_ttls_isKeyAvailable;
1686 eap->getKey = eap_ttls_getKey;
1687 eap->getSessionId = eap_ttls_get_session_id;
1688 eap->get_status = eap_ttls_get_status;
1689 eap->has_reauth_data = eap_ttls_has_reauth_data;
1690 eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
1691 eap->init_for_reauth = eap_ttls_init_for_reauth;
1692 eap->get_emsk = eap_ttls_get_emsk;
1694 ret = eap_peer_method_register(eap);
1696 eap_peer_method_free(eap);