2 * hostapd / EAP-TTLS (draft-ietf-pppext-eap-ttls-05.txt)
3 * Copyright (c) 2004-2007, 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.
20 #include "eap_tls_common.h"
29 /* Maximum supported PEAP version
30 * 0 = draft-ietf-pppext-eap-ttls-03.txt / draft-funk-eap-ttls-v0-00.txt
31 * 1 = draft-funk-eap-ttls-v1-00.txt
33 #define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
36 #define MSCHAPV2_KEY_LEN 16
39 static void eap_ttls_reset(struct eap_sm
*sm
, void *priv
);
42 struct eap_ttls_data
{
43 struct eap_ssl_data ssl
;
45 START
, PHASE1
, PHASE2_START
, PHASE2_METHOD
,
46 PHASE2_MSCHAPV2_RESP
, PHASE_FINISHED
, SUCCESS
, FAILURE
51 const struct eap_method
*phase2_method
;
54 u8 mschapv2_auth_response
[20];
56 int tls_ia_configured
;
60 static const char * eap_ttls_state_txt(int state
)
68 return "PHASE2_START";
70 return "PHASE2_METHOD";
71 case PHASE2_MSCHAPV2_RESP
:
72 return "PHASE2_MSCHAPV2_RESP";
74 return "PHASE_FINISHED";
85 static void eap_ttls_state(struct eap_ttls_data
*data
, int state
)
87 wpa_printf(MSG_DEBUG
, "EAP-TTLS: %s -> %s",
88 eap_ttls_state_txt(data
->state
),
89 eap_ttls_state_txt(state
));
94 static u8
* eap_ttls_avp_hdr(u8
*avphdr
, u32 avp_code
, u32 vendor_id
,
95 int mandatory
, size_t len
)
97 struct ttls_avp_vendor
*avp
;
101 avp
= (struct ttls_avp_vendor
*) avphdr
;
102 flags
= mandatory
? AVP_FLAGS_MANDATORY
: 0;
104 flags
|= AVP_FLAGS_VENDOR
;
105 hdrlen
= sizeof(*avp
);
106 avp
->vendor_id
= host_to_be32(vendor_id
);
108 hdrlen
= sizeof(struct ttls_avp
);
111 avp
->avp_code
= host_to_be32(avp_code
);
112 avp
->avp_length
= host_to_be32((flags
<< 24) | (hdrlen
+ len
));
114 return avphdr
+ hdrlen
;
118 static int eap_ttls_avp_encapsulate(u8
**resp
, size_t *resp_len
, u32 avp_code
,
123 avp
= malloc(sizeof(struct ttls_avp
) + *resp_len
+ 4);
130 pos
= eap_ttls_avp_hdr(avp
, avp_code
, 0, mandatory
, *resp_len
);
131 memcpy(pos
, *resp
, *resp_len
);
136 *resp_len
= pos
- avp
;
141 struct eap_ttls_avp
{
142 /* Note: eap is allocated memory; caller is responsible for freeing
143 * it. All the other pointers are pointing to the packet data, i.e.,
144 * they must not be freed separately. */
148 size_t user_name_len
;
150 size_t user_password_len
;
152 size_t chap_challenge_len
;
154 size_t chap_password_len
;
155 u8
*mschap_challenge
;
156 size_t mschap_challenge_len
;
158 size_t mschap_response_len
;
159 u8
*mschap2_response
;
160 size_t mschap2_response_len
;
164 static int eap_ttls_avp_parse(u8
*buf
, size_t len
, struct eap_ttls_avp
*parse
)
166 struct ttls_avp
*avp
;
172 memset(parse
, 0, sizeof(*parse
));
175 u32 avp_code
, avp_length
, vendor_id
= 0;
178 avp
= (struct ttls_avp
*) pos
;
179 avp_code
= be_to_host32(avp
->avp_code
);
180 avp_length
= be_to_host32(avp
->avp_length
);
181 avp_flags
= (avp_length
>> 24) & 0xff;
182 avp_length
&= 0xffffff;
183 wpa_printf(MSG_DEBUG
, "EAP-TTLS: AVP: code=%d flags=0x%02x "
184 "length=%d", (int) avp_code
, avp_flags
,
186 if ((int) avp_length
> left
) {
187 wpa_printf(MSG_WARNING
, "EAP-TTLS: AVP overflow "
188 "(len=%d, left=%d) - dropped",
189 (int) avp_length
, left
);
192 if (avp_length
< sizeof(*avp
)) {
193 wpa_printf(MSG_WARNING
, "EAP-TTLS: Invalid AVP length "
197 dpos
= (u8
*) (avp
+ 1);
198 dlen
= avp_length
- sizeof(*avp
);
199 if (avp_flags
& AVP_FLAGS_VENDOR
) {
201 wpa_printf(MSG_WARNING
, "EAP-TTLS: vendor AVP "
205 vendor_id
= be_to_host32(* (u32
*) dpos
);
206 wpa_printf(MSG_DEBUG
, "EAP-TTLS: AVP vendor_id %d",
212 wpa_hexdump(MSG_DEBUG
, "EAP-TTLS: AVP data", dpos
, dlen
);
214 if (vendor_id
== 0 && avp_code
== RADIUS_ATTR_EAP_MESSAGE
) {
215 wpa_printf(MSG_DEBUG
, "EAP-TTLS: AVP - EAP Message");
216 if (parse
->eap
== NULL
) {
217 parse
->eap
= malloc(dlen
);
218 if (parse
->eap
== NULL
) {
219 wpa_printf(MSG_WARNING
, "EAP-TTLS: "
220 "failed to allocate memory "
221 "for Phase 2 EAP data");
224 memcpy(parse
->eap
, dpos
, dlen
);
225 parse
->eap_len
= dlen
;
227 u8
*neweap
= realloc(parse
->eap
,
228 parse
->eap_len
+ dlen
);
229 if (neweap
== NULL
) {
230 wpa_printf(MSG_WARNING
, "EAP-TTLS: "
231 "failed to allocate memory "
232 "for Phase 2 EAP data");
235 memcpy(neweap
+ parse
->eap_len
, dpos
, dlen
);
237 parse
->eap_len
+= dlen
;
239 } else if (vendor_id
== 0 &&
240 avp_code
== RADIUS_ATTR_USER_NAME
) {
241 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TTLS: User-Name",
243 parse
->user_name
= dpos
;
244 parse
->user_name_len
= dlen
;
245 } else if (vendor_id
== 0 &&
246 avp_code
== RADIUS_ATTR_USER_PASSWORD
) {
248 size_t password_len
= dlen
;
249 while (password_len
> 0 &&
250 password
[password_len
- 1] == '\0') {
253 wpa_hexdump_ascii_key(MSG_DEBUG
, "EAP-TTLS: "
254 "User-Password (PAP)",
255 password
, password_len
);
256 parse
->user_password
= password
;
257 parse
->user_password_len
= password_len
;
258 } else if (vendor_id
== 0 &&
259 avp_code
== RADIUS_ATTR_CHAP_CHALLENGE
) {
260 wpa_hexdump(MSG_DEBUG
,
261 "EAP-TTLS: CHAP-Challenge (CHAP)",
263 parse
->chap_challenge
= dpos
;
264 parse
->chap_challenge_len
= dlen
;
265 } else if (vendor_id
== 0 &&
266 avp_code
== RADIUS_ATTR_CHAP_PASSWORD
) {
267 wpa_hexdump(MSG_DEBUG
,
268 "EAP-TTLS: CHAP-Password (CHAP)",
270 parse
->chap_password
= dpos
;
271 parse
->chap_password_len
= dlen
;
272 } else if (vendor_id
== RADIUS_VENDOR_ID_MICROSOFT
&&
273 avp_code
== RADIUS_ATTR_MS_CHAP_CHALLENGE
) {
274 wpa_hexdump(MSG_DEBUG
,
275 "EAP-TTLS: MS-CHAP-Challenge",
277 parse
->mschap_challenge
= dpos
;
278 parse
->mschap_challenge_len
= dlen
;
279 } else if (vendor_id
== RADIUS_VENDOR_ID_MICROSOFT
&&
280 avp_code
== RADIUS_ATTR_MS_CHAP_RESPONSE
) {
281 wpa_hexdump(MSG_DEBUG
,
282 "EAP-TTLS: MS-CHAP-Response (MSCHAP)",
284 parse
->mschap_response
= dpos
;
285 parse
->mschap_response_len
= dlen
;
286 } else if (vendor_id
== RADIUS_VENDOR_ID_MICROSOFT
&&
287 avp_code
== RADIUS_ATTR_MS_CHAP2_RESPONSE
) {
288 wpa_hexdump(MSG_DEBUG
,
289 "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)",
291 parse
->mschap2_response
= dpos
;
292 parse
->mschap2_response_len
= dlen
;
293 } else if (avp_flags
& AVP_FLAGS_MANDATORY
) {
294 wpa_printf(MSG_WARNING
, "EAP-TTLS: Unsupported "
295 "mandatory AVP code %d vendor_id %d - "
296 "dropped", (int) avp_code
, (int) vendor_id
);
299 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Ignoring unsupported "
300 "AVP code %d vendor_id %d",
301 (int) avp_code
, (int) vendor_id
);
304 pad
= (4 - (avp_length
& 3)) & 3;
305 pos
+= avp_length
+ pad
;
306 left
-= avp_length
+ pad
;
318 static u8
* eap_ttls_implicit_challenge(struct eap_sm
*sm
,
319 struct eap_ttls_data
*data
, size_t len
)
321 struct tls_keys keys
;
324 if (data
->ttls_version
== 0) {
325 return eap_tls_derive_key(sm
, &data
->ssl
, "ttls challenge",
329 memset(&keys
, 0, sizeof(keys
));
330 if (tls_connection_get_keys(sm
->ssl_ctx
, data
->ssl
.conn
, &keys
) ||
331 keys
.client_random
== NULL
|| keys
.server_random
== NULL
||
332 keys
.inner_secret
== NULL
) {
333 wpa_printf(MSG_INFO
, "EAP-TTLS: Could not get inner secret, "
334 "client random, or server random to derive "
335 "implicit challenge");
339 rnd
= malloc(keys
.client_random_len
+ keys
.server_random_len
);
340 challenge
= malloc(len
);
341 if (rnd
== NULL
|| challenge
== NULL
) {
342 wpa_printf(MSG_INFO
, "EAP-TTLS: No memory for implicit "
343 "challenge derivation");
348 memcpy(rnd
, keys
.server_random
, keys
.server_random_len
);
349 memcpy(rnd
+ keys
.server_random_len
, keys
.client_random
,
350 keys
.client_random_len
);
352 if (tls_prf(keys
.inner_secret
, keys
.inner_secret_len
,
353 "inner application challenge", rnd
,
354 keys
.client_random_len
+ keys
.server_random_len
,
356 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Failed to derive implicit "
365 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS: Derived implicit challenge",
372 static void * eap_ttls_init(struct eap_sm
*sm
)
374 struct eap_ttls_data
*data
;
376 data
= wpa_zalloc(sizeof(*data
));
379 data
->ttls_version
= EAP_TTLS_VERSION
;
380 data
->force_version
= -1;
381 if (sm
->user
&& sm
->user
->force_version
>= 0) {
382 data
->force_version
= sm
->user
->force_version
;
383 wpa_printf(MSG_DEBUG
, "EAP-TTLS: forcing version %d",
384 data
->force_version
);
385 data
->ttls_version
= data
->force_version
;
389 if (!(tls_capabilities(sm
->ssl_ctx
) & TLS_CAPABILITY_IA
) &&
390 data
->ttls_version
> 0) {
391 if (data
->force_version
> 0) {
392 wpa_printf(MSG_INFO
, "EAP-TTLS: Forced TTLSv%d and "
393 "TLS library does not support TLS/IA.",
394 data
->force_version
);
395 eap_ttls_reset(sm
, data
);
398 data
->ttls_version
= 0;
401 if (eap_tls_ssl_init(sm
, &data
->ssl
, 0)) {
402 wpa_printf(MSG_INFO
, "EAP-TTLS: Failed to initialize SSL.");
403 eap_ttls_reset(sm
, data
);
411 static void eap_ttls_reset(struct eap_sm
*sm
, void *priv
)
413 struct eap_ttls_data
*data
= priv
;
416 if (data
->phase2_priv
&& data
->phase2_method
)
417 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
418 eap_tls_ssl_deinit(sm
, &data
->ssl
);
423 static u8
* eap_ttls_build_start(struct eap_sm
*sm
, struct eap_ttls_data
*data
,
424 int id
, size_t *reqDataLen
)
429 *reqDataLen
= sizeof(*req
) + 2;
430 req
= malloc(*reqDataLen
);
432 wpa_printf(MSG_ERROR
, "EAP-TTLS: Failed to allocate memory for"
434 eap_ttls_state(data
, FAILURE
);
438 req
->code
= EAP_CODE_REQUEST
;
439 req
->identifier
= id
;
440 req
->length
= htons(*reqDataLen
);
441 pos
= (u8
*) (req
+ 1);
442 *pos
++ = EAP_TYPE_TTLS
;
443 *pos
= EAP_TLS_FLAGS_START
| data
->ttls_version
;
445 eap_ttls_state(data
, PHASE1
);
451 static u8
* eap_ttls_build_req(struct eap_sm
*sm
, struct eap_ttls_data
*data
,
452 int id
, size_t *reqDataLen
)
457 res
= eap_tls_buildReq_helper(sm
, &data
->ssl
, EAP_TYPE_TTLS
,
458 data
->ttls_version
, id
, &req
,
461 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
462 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Phase1 done, starting "
464 eap_ttls_state(data
, PHASE2_START
);
468 return eap_tls_build_ack(reqDataLen
, id
, EAP_TYPE_TTLS
,
474 static u8
* eap_ttls_encrypt(struct eap_sm
*sm
, struct eap_ttls_data
*data
,
475 int id
, u8
*plain
, size_t plain_len
,
482 /* TODO: add support for fragmentation, if needed. This will need to
483 * add TLS Message Length field, if the frame is fragmented. */
484 req
= malloc(sizeof(struct eap_hdr
) + 2 + data
->ssl
.tls_out_limit
);
488 req
->code
= EAP_CODE_REQUEST
;
489 req
->identifier
= id
;
491 pos
= (u8
*) (req
+ 1);
492 *pos
++ = EAP_TYPE_TTLS
;
493 *pos
++ = data
->ttls_version
;
495 res
= tls_connection_encrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
497 pos
, data
->ssl
.tls_out_limit
);
499 wpa_printf(MSG_INFO
, "EAP-TTLS: Failed to encrypt Phase 2 "
505 *out_len
= sizeof(struct eap_hdr
) + 2 + res
;
506 req
->length
= host_to_be16(*out_len
);
511 static u8
* eap_ttls_build_phase2_eap_req(struct eap_sm
*sm
,
512 struct eap_ttls_data
*data
,
513 int id
, size_t *reqDataLen
)
519 req
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, id
,
524 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS/EAP: Encapsulate Phase 2 data",
527 if (eap_ttls_avp_encapsulate(&req
, &req_len
, RADIUS_ATTR_EAP_MESSAGE
,
529 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: Failed to encapsulate "
534 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
535 "2 data", req
, req_len
);
537 encr_req
= eap_ttls_encrypt(sm
, data
, id
, req
, req_len
, reqDataLen
);
544 static u8
* eap_ttls_build_phase2_mschapv2(struct eap_sm
*sm
,
545 struct eap_ttls_data
*data
,
546 int id
, size_t *reqDataLen
)
548 u8
*req
, *encr_req
, *pos
, *end
;
552 pos
= req
= malloc(100);
557 if (data
->mschapv2_resp_ok
) {
558 pos
= eap_ttls_avp_hdr(pos
, RADIUS_ATTR_MS_CHAP2_SUCCESS
,
559 RADIUS_VENDOR_ID_MICROSOFT
, 1, 43);
560 *pos
++ = data
->mschapv2_ident
;
561 ret
= snprintf((char *) pos
, end
- pos
, "S=");
562 if (ret
>= 0 && ret
< end
- pos
)
564 pos
+= wpa_snprintf_hex_uppercase(
565 (char *) pos
, end
- pos
, data
->mschapv2_auth_response
,
566 sizeof(data
->mschapv2_auth_response
));
568 pos
= eap_ttls_avp_hdr(pos
, RADIUS_ATTR_MS_CHAP_ERROR
,
569 RADIUS_VENDOR_ID_MICROSOFT
, 1, 6);
570 memcpy(pos
, "Failed", 6);
576 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
577 "data", req
, req_len
);
579 encr_req
= eap_ttls_encrypt(sm
, data
, id
, req
, req_len
, reqDataLen
);
586 static u8
* eap_ttls_build_phase_finished(struct eap_sm
*sm
,
587 struct eap_ttls_data
*data
,
594 const int max_len
= 300;
596 len
= sizeof(struct eap_hdr
) + 2 + max_len
;
601 req
->code
= EAP_CODE_REQUEST
;
602 req
->identifier
= id
;
604 pos
= (u8
*) (req
+ 1);
605 *pos
++ = EAP_TYPE_TTLS
;
606 *pos
++ = data
->ttls_version
;
608 len
= tls_connection_ia_send_phase_finished(sm
->ssl_ctx
,
610 final
, pos
, max_len
);
616 *reqDataLen
= sizeof(struct eap_hdr
) + 2 + len
;
617 req
->length
= host_to_be16(*reqDataLen
);
623 static u8
* eap_ttls_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
626 struct eap_ttls_data
*data
= priv
;
628 switch (data
->state
) {
630 return eap_ttls_build_start(sm
, data
, id
, reqDataLen
);
632 return eap_ttls_build_req(sm
, data
, id
, reqDataLen
);
634 return eap_ttls_build_phase2_eap_req(sm
, data
, id
, reqDataLen
);
635 case PHASE2_MSCHAPV2_RESP
:
636 return eap_ttls_build_phase2_mschapv2(sm
, data
, id
,
639 return eap_ttls_build_phase_finished(sm
, data
, id
, 1,
642 wpa_printf(MSG_DEBUG
, "EAP-TTLS: %s - unexpected state %d",
643 __func__
, data
->state
);
649 static Boolean
eap_ttls_check(struct eap_sm
*sm
, void *priv
,
650 u8
*respData
, size_t respDataLen
)
652 struct eap_hdr
*resp
;
655 resp
= (struct eap_hdr
*) respData
;
656 pos
= (u8
*) (resp
+ 1);
657 if (respDataLen
< sizeof(*resp
) + 2 || *pos
!= EAP_TYPE_TTLS
||
658 (ntohs(resp
->length
)) > respDataLen
) {
659 wpa_printf(MSG_INFO
, "EAP-TTLS: Invalid frame");
667 static int eap_ttls_ia_permute_inner_secret(struct eap_sm
*sm
,
668 struct eap_ttls_data
*data
,
669 const u8
*key
, size_t key_len
)
676 buf_len
= 2 + key_len
;
677 buf
= malloc(buf_len
);
680 WPA_PUT_BE16(buf
, key_len
);
681 memcpy(buf
+ 2, key
, key_len
);
687 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS: Session keys for TLS/IA inner "
688 "secret permutation", buf
, buf_len
);
689 ret
= tls_connection_ia_permute_inner_secret(sm
->ssl_ctx
,
698 static void eap_ttls_process_phase2_pap(struct eap_sm
*sm
,
699 struct eap_ttls_data
*data
,
700 const u8
*user_password
,
701 size_t user_password_len
)
703 /* TODO: add support for verifying that the user entry accepts
705 if (!sm
->user
|| !sm
->user
->password
|| sm
->user
->password_hash
) {
706 wpa_printf(MSG_DEBUG
, "EAP-TTLS/PAP: No plaintext user "
707 "password configured");
708 eap_ttls_state(data
, FAILURE
);
712 if (sm
->user
->password_len
!= user_password_len
||
713 memcmp(sm
->user
->password
, user_password
, user_password_len
) != 0)
715 wpa_printf(MSG_DEBUG
, "EAP-TTLS/PAP: Invalid user password");
716 eap_ttls_state(data
, FAILURE
);
720 wpa_printf(MSG_DEBUG
, "EAP-TTLS/PAP: Correct user password");
721 eap_ttls_state(data
, data
->ttls_version
> 0 ? PHASE_FINISHED
:
726 static void eap_ttls_process_phase2_chap(struct eap_sm
*sm
,
727 struct eap_ttls_data
*data
,
729 size_t challenge_len
,
733 u8
*chal
, hash
[MD5_MAC_LEN
];
737 if (challenge
== NULL
|| password
== NULL
||
738 challenge_len
!= EAP_TTLS_CHAP_CHALLENGE_LEN
||
739 password_len
!= 1 + EAP_TTLS_CHAP_PASSWORD_LEN
) {
740 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: Invalid CHAP attributes "
741 "(challenge len %lu password len %lu)",
742 (unsigned long) challenge_len
,
743 (unsigned long) password_len
);
744 eap_ttls_state(data
, FAILURE
);
748 /* TODO: add support for verifying that the user entry accepts
750 if (!sm
->user
|| !sm
->user
->password
|| sm
->user
->password_hash
) {
751 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: No plaintext user "
752 "password configured");
753 eap_ttls_state(data
, FAILURE
);
757 chal
= eap_ttls_implicit_challenge(sm
, data
,
758 EAP_TTLS_CHAP_CHALLENGE_LEN
+ 1);
760 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: Failed to generate "
761 "challenge from TLS data");
762 eap_ttls_state(data
, FAILURE
);
766 if (memcmp(challenge
, chal
, EAP_TTLS_CHAP_CHALLENGE_LEN
) != 0 ||
767 password
[0] != chal
[EAP_TTLS_CHAP_CHALLENGE_LEN
]) {
768 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: Challenge mismatch");
770 eap_ttls_state(data
, FAILURE
);
775 /* MD5(Ident + Password + Challenge) */
778 addr
[1] = sm
->user
->password
;
779 len
[1] = sm
->user
->password_len
;
781 len
[2] = challenge_len
;
782 md5_vector(3, addr
, len
, hash
);
784 if (memcmp(hash
, password
+ 1, EAP_TTLS_CHAP_PASSWORD_LEN
) == 0) {
785 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: Correct user password");
786 eap_ttls_state(data
, data
->ttls_version
> 0 ? PHASE_FINISHED
:
789 wpa_printf(MSG_DEBUG
, "EAP-TTLS/CHAP: Invalid user password");
790 eap_ttls_state(data
, FAILURE
);
795 static void eap_ttls_process_phase2_mschap(struct eap_sm
*sm
,
796 struct eap_ttls_data
*data
,
797 u8
*challenge
, size_t challenge_len
,
798 u8
*response
, size_t response_len
)
800 u8
*chal
, nt_response
[24];
802 if (challenge
== NULL
|| response
== NULL
||
803 challenge_len
!= EAP_TTLS_MSCHAP_CHALLENGE_LEN
||
804 response_len
!= EAP_TTLS_MSCHAP_RESPONSE_LEN
) {
805 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: Invalid MS-CHAP "
806 "attributes (challenge len %lu response len %lu)",
807 (unsigned long) challenge_len
,
808 (unsigned long) response_len
);
809 eap_ttls_state(data
, FAILURE
);
813 /* TODO: add support for verifying that the user entry accepts
814 * EAP-TTLS/MSCHAP. */
815 if (!sm
->user
|| !sm
->user
->password
) {
816 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: No user password "
818 eap_ttls_state(data
, FAILURE
);
822 chal
= eap_ttls_implicit_challenge(sm
, data
,
823 EAP_TTLS_MSCHAP_CHALLENGE_LEN
+ 1);
825 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: Failed to generate "
826 "challenge from TLS data");
827 eap_ttls_state(data
, FAILURE
);
831 if (memcmp(challenge
, chal
, EAP_TTLS_MSCHAP_CHALLENGE_LEN
) != 0 ||
832 response
[0] != chal
[EAP_TTLS_MSCHAP_CHALLENGE_LEN
]) {
833 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: Challenge mismatch");
835 eap_ttls_state(data
, FAILURE
);
840 if (sm
->user
->password_hash
)
841 challenge_response(challenge
, sm
->user
->password
, nt_response
);
843 nt_challenge_response(challenge
, sm
->user
->password
,
844 sm
->user
->password_len
, nt_response
);
846 if (memcmp(nt_response
, response
+ 2 + 24, 24) == 0) {
847 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: Correct response");
848 eap_ttls_state(data
, data
->ttls_version
> 0 ? PHASE_FINISHED
:
851 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAP: Invalid NT-Response");
852 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAP: Received",
853 response
+ 2 + 24, 24);
854 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAP: Expected",
856 eap_ttls_state(data
, FAILURE
);
861 static void eap_ttls_process_phase2_mschapv2(struct eap_sm
*sm
,
862 struct eap_ttls_data
*data
,
864 size_t challenge_len
,
865 u8
*response
, size_t response_len
)
867 u8
*chal
, *username
, nt_response
[24], *rx_resp
, *peer_challenge
,
869 size_t username_len
, i
;
871 if (challenge
== NULL
|| response
== NULL
||
872 challenge_len
!= EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
||
873 response_len
!= EAP_TTLS_MSCHAPV2_RESPONSE_LEN
) {
874 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 "
875 "attributes (challenge len %lu response len %lu)",
876 (unsigned long) challenge_len
,
877 (unsigned long) response_len
);
878 eap_ttls_state(data
, FAILURE
);
882 /* TODO: add support for verifying that the user entry accepts
883 * EAP-TTLS/MSCHAPV2. */
884 if (!sm
->user
|| !sm
->user
->password
) {
885 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: No user password "
887 eap_ttls_state(data
, FAILURE
);
891 /* MSCHAPv2 does not include optional domain name in the
892 * challenge-response calculation, so remove domain prefix
894 username
= sm
->identity
;
895 username_len
= sm
->identity_len
;
896 for (i
= 0; i
< username_len
; i
++) {
897 if (username
[i
] == '\\') {
898 username_len
-= i
+ 1;
904 chal
= eap_ttls_implicit_challenge(
905 sm
, data
, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
+ 1);
907 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Failed to generate "
908 "challenge from TLS data");
909 eap_ttls_state(data
, FAILURE
);
913 if (memcmp(challenge
, chal
, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
) != 0 ||
914 response
[0] != chal
[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
]) {
915 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
917 eap_ttls_state(data
, FAILURE
);
922 auth_challenge
= challenge
;
923 peer_challenge
= response
+ 2;
925 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-TTLS/MSCHAPV2: User",
926 username
, username_len
);
927 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAPV2: auth_challenge",
928 auth_challenge
, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
);
929 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAPV2: peer_challenge",
930 peer_challenge
, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
);
932 if (sm
->user
->password_hash
) {
933 generate_nt_response_pwhash(auth_challenge
, peer_challenge
,
934 username
, username_len
,
938 generate_nt_response(auth_challenge
, peer_challenge
,
939 username
, username_len
,
941 sm
->user
->password_len
,
945 rx_resp
= response
+ 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN
+ 8;
946 if (memcmp(nt_response
, rx_resp
, 24) == 0) {
947 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Correct "
949 data
->mschapv2_resp_ok
= 1;
950 if (data
->ttls_version
> 0) {
952 u8 pw_hash_buf
[16], pw_hash_hash
[16], master_key
[16];
953 u8 session_key
[2 * MSCHAPV2_KEY_LEN
];
955 if (sm
->user
->password_hash
)
956 pw_hash
= sm
->user
->password
;
958 nt_password_hash(sm
->user
->password
,
959 sm
->user
->password_len
,
961 pw_hash
= pw_hash_buf
;
963 hash_nt_password_hash(pw_hash
, pw_hash_hash
);
964 get_master_key(pw_hash_hash
, nt_response
, master_key
);
965 get_asymetric_start_key(master_key
, session_key
,
966 MSCHAPV2_KEY_LEN
, 0, 0);
967 get_asymetric_start_key(master_key
,
968 session_key
+ MSCHAPV2_KEY_LEN
,
969 MSCHAPV2_KEY_LEN
, 1, 0);
970 eap_ttls_ia_permute_inner_secret(sm
, data
,
972 sizeof(session_key
));
975 if (sm
->user
->password_hash
) {
976 generate_authenticator_response_pwhash(
978 peer_challenge
, auth_challenge
,
979 username
, username_len
, nt_response
,
980 data
->mschapv2_auth_response
);
982 generate_authenticator_response(
983 sm
->user
->password
, sm
->user
->password_len
,
984 peer_challenge
, auth_challenge
,
985 username
, username_len
, nt_response
,
986 data
->mschapv2_auth_response
);
989 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Invalid "
991 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAPV2: Received",
993 wpa_hexdump(MSG_MSGDUMP
, "EAP-TTLS/MSCHAPV2: Expected",
995 data
->mschapv2_resp_ok
= 0;
997 eap_ttls_state(data
, PHASE2_MSCHAPV2_RESP
);
998 data
->mschapv2_ident
= response
[0];
1002 static int eap_ttls_phase2_eap_init(struct eap_sm
*sm
,
1003 struct eap_ttls_data
*data
,
1006 if (data
->phase2_priv
&& data
->phase2_method
) {
1007 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
1008 data
->phase2_method
= NULL
;
1009 data
->phase2_priv
= NULL
;
1011 data
->phase2_method
= eap_sm_get_eap_methods(EAP_VENDOR_IETF
,
1013 if (!data
->phase2_method
)
1016 sm
->init_phase2
= 1;
1017 data
->phase2_priv
= data
->phase2_method
->init(sm
);
1018 sm
->init_phase2
= 0;
1023 static void eap_ttls_process_phase2_eap_response(struct eap_sm
*sm
,
1024 struct eap_ttls_data
*data
,
1025 u8
*in_data
, size_t in_len
)
1027 u8 next_type
= EAP_TYPE_NONE
;
1028 struct eap_hdr
*hdr
;
1031 const struct eap_method
*m
= data
->phase2_method
;
1032 void *priv
= data
->phase2_priv
;
1034 if (data
->phase2_priv
== NULL
) {
1035 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: %s - Phase2 not "
1036 "initialized?!", __func__
);
1040 hdr
= (struct eap_hdr
*) in_data
;
1041 pos
= (u8
*) (hdr
+ 1);
1043 if (in_len
> sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
1044 left
= in_len
- sizeof(*hdr
);
1045 wpa_hexdump(MSG_DEBUG
, "EAP-TTLS/EAP: Phase2 type Nak'ed; "
1046 "allowed types", pos
+ 1, left
- 1);
1047 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
1048 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
1049 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
1051 next_type
= sm
->user
->methods
[
1052 sm
->user_eap_method_index
++].method
;
1053 wpa_printf(MSG_DEBUG
, "EAP-TTLS: try EAP type %d",
1055 eap_ttls_phase2_eap_init(sm
, data
, next_type
);
1057 eap_ttls_state(data
, FAILURE
);
1062 if (m
->check(sm
, priv
, in_data
, in_len
)) {
1063 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: Phase2 check() asked to "
1064 "ignore the packet");
1068 m
->process(sm
, priv
, in_data
, in_len
);
1070 if (!m
->isDone(sm
, priv
))
1073 if (!m
->isSuccess(sm
, priv
)) {
1074 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: Phase2 method failed");
1075 eap_ttls_state(data
, FAILURE
);
1079 switch (data
->state
) {
1081 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1082 wpa_hexdump_ascii(MSG_DEBUG
, "EAP_TTLS: Phase2 "
1083 "Identity not found in the user "
1085 sm
->identity
, sm
->identity_len
);
1086 eap_ttls_state(data
, FAILURE
);
1090 eap_ttls_state(data
, PHASE2_METHOD
);
1091 next_type
= sm
->user
->methods
[0].method
;
1092 sm
->user_eap_method_index
= 1;
1093 wpa_printf(MSG_DEBUG
, "EAP-TTLS: try EAP type %d", next_type
);
1096 if (data
->ttls_version
> 0) {
1100 key
= m
->getKey(sm
, priv
, &key_len
);
1101 eap_ttls_ia_permute_inner_secret(sm
, data
,
1104 eap_ttls_state(data
, PHASE_FINISHED
);
1106 eap_ttls_state(data
, SUCCESS
);
1111 wpa_printf(MSG_DEBUG
, "EAP-TTLS: %s - unexpected state %d",
1112 __func__
, data
->state
);
1116 eap_ttls_phase2_eap_init(sm
, data
, next_type
);
1120 static void eap_ttls_process_phase2_eap(struct eap_sm
*sm
,
1121 struct eap_ttls_data
*data
,
1122 const u8
*eap
, size_t eap_len
)
1124 struct eap_hdr
*hdr
;
1127 if (data
->state
== PHASE2_START
) {
1128 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: initializing Phase 2");
1129 if (eap_ttls_phase2_eap_init(sm
, data
, EAP_TYPE_IDENTITY
) < 0)
1131 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: failed to "
1132 "initialize EAP-Identity");
1137 if (eap_len
< sizeof(*hdr
)) {
1138 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: too short Phase 2 EAP "
1139 "packet (len=%lu)", (unsigned long) eap_len
);
1143 hdr
= (struct eap_hdr
*) eap
;
1144 len
= be_to_host16(hdr
->length
);
1145 wpa_printf(MSG_DEBUG
, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "
1146 "identifier=%d length=%lu", hdr
->code
, hdr
->identifier
,
1147 (unsigned long) len
);
1148 if (len
> eap_len
) {
1149 wpa_printf(MSG_INFO
, "EAP-TTLS/EAP: Length mismatch in Phase 2"
1150 " EAP frame (hdr len=%lu, data len in AVP=%lu)",
1151 (unsigned long) len
, (unsigned long) eap_len
);
1155 switch (hdr
->code
) {
1156 case EAP_CODE_RESPONSE
:
1157 eap_ttls_process_phase2_eap_response(sm
, data
, (u8
*) hdr
,
1161 wpa_printf(MSG_INFO
, "EAP-TTLS/EAP: Unexpected code=%d in "
1162 "Phase 2 EAP header", hdr
->code
);
1168 static void eap_ttls_process_phase2(struct eap_sm
*sm
,
1169 struct eap_ttls_data
*data
,
1170 struct eap_hdr
*resp
,
1171 u8
*in_data
, size_t in_len
)
1174 int len_decrypted
, res
;
1175 struct eap_ttls_avp parse
;
1178 wpa_printf(MSG_DEBUG
, "EAP-TTLS: received %lu bytes encrypted data for"
1179 " Phase 2", (unsigned long) in_len
);
1181 res
= eap_tls_data_reassemble(sm
, &data
->ssl
, &in_data
, &in_len
);
1182 if (res
< 0 || res
== 1)
1186 if (data
->ssl
.tls_in_total
> buf_len
)
1187 buf_len
= data
->ssl
.tls_in_total
;
1188 in_decrypted
= malloc(buf_len
);
1189 if (in_decrypted
== NULL
) {
1190 free(data
->ssl
.tls_in
);
1191 data
->ssl
.tls_in
= NULL
;
1192 data
->ssl
.tls_in_len
= 0;
1193 wpa_printf(MSG_WARNING
, "EAP-TTLS: failed to allocate memory "
1198 len_decrypted
= tls_connection_decrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1200 in_decrypted
, buf_len
);
1201 free(data
->ssl
.tls_in
);
1202 data
->ssl
.tls_in
= NULL
;
1203 data
->ssl
.tls_in_len
= 0;
1204 if (len_decrypted
< 0) {
1205 wpa_printf(MSG_INFO
, "EAP-TTLS: Failed to decrypt Phase 2 "
1208 eap_ttls_state(data
, FAILURE
);
1212 if (data
->state
== PHASE_FINISHED
) {
1213 if (len_decrypted
== 0 &&
1214 tls_connection_ia_final_phase_finished(sm
->ssl_ctx
,
1216 wpa_printf(MSG_DEBUG
, "EAP-TTLS: FinalPhaseFinished "
1218 eap_ttls_state(data
, SUCCESS
);
1220 wpa_printf(MSG_INFO
, "EAP-TTLS: Did not receive valid "
1221 "FinalPhaseFinished");
1222 eap_ttls_state(data
, FAILURE
);
1229 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS: Decrypted Phase 2 EAP",
1230 in_decrypted
, len_decrypted
);
1232 if (eap_ttls_avp_parse(in_decrypted
, len_decrypted
, &parse
) < 0) {
1233 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Failed to parse AVPs");
1235 eap_ttls_state(data
, FAILURE
);
1239 if (parse
.user_name
) {
1241 sm
->identity
= malloc(parse
.user_name_len
);
1243 memcpy(sm
->identity
, parse
.user_name
,
1244 parse
.user_name_len
);
1245 sm
->identity_len
= parse
.user_name_len
;
1247 if (eap_user_get(sm
, parse
.user_name
, parse
.user_name_len
, 1)
1249 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Phase2 Identity not "
1250 "found in the user database");
1251 eap_ttls_state(data
, FAILURE
);
1257 eap_ttls_process_phase2_eap(sm
, data
, parse
.eap
,
1259 } else if (parse
.user_password
) {
1260 eap_ttls_process_phase2_pap(sm
, data
, parse
.user_password
,
1261 parse
.user_password_len
);
1262 } else if (parse
.chap_password
) {
1263 eap_ttls_process_phase2_chap(sm
, data
,
1264 parse
.chap_challenge
,
1265 parse
.chap_challenge_len
,
1266 parse
.chap_password
,
1267 parse
.chap_password_len
);
1268 } else if (parse
.mschap_response
) {
1269 eap_ttls_process_phase2_mschap(sm
, data
,
1270 parse
.mschap_challenge
,
1271 parse
.mschap_challenge_len
,
1272 parse
.mschap_response
,
1273 parse
.mschap_response_len
);
1274 } else if (parse
.mschap2_response
) {
1275 eap_ttls_process_phase2_mschapv2(sm
, data
,
1276 parse
.mschap_challenge
,
1277 parse
.mschap_challenge_len
,
1278 parse
.mschap2_response
,
1279 parse
.mschap2_response_len
);
1288 static void eap_ttls_process(struct eap_sm
*sm
, void *priv
,
1289 u8
*respData
, size_t respDataLen
)
1291 struct eap_ttls_data
*data
= priv
;
1292 struct eap_hdr
*resp
;
1295 unsigned int tls_msg_len
;
1298 resp
= (struct eap_hdr
*) respData
;
1299 pos
= (u8
*) (resp
+ 1);
1302 left
= htons(resp
->length
) - sizeof(struct eap_hdr
) - 2;
1303 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Received packet(len=%lu) - "
1304 "Flags 0x%02x", (unsigned long) respDataLen
, flags
);
1305 peer_version
= flags
& EAP_PEAP_VERSION_MASK
;
1306 if (peer_version
< data
->ttls_version
) {
1307 wpa_printf(MSG_DEBUG
, "EAP-TTLS: peer ver=%d, own ver=%d; "
1309 peer_version
, data
->ttls_version
, peer_version
);
1310 data
->ttls_version
= peer_version
;
1313 if (data
->ttls_version
> 0 && !data
->tls_ia_configured
) {
1314 if (tls_connection_set_ia(sm
->ssl_ctx
, data
->ssl
.conn
, 1)) {
1315 wpa_printf(MSG_INFO
, "EAP-TTLS: Failed to enable "
1317 eap_ttls_state(data
, FAILURE
);
1320 data
->tls_ia_configured
= 1;
1323 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
1325 wpa_printf(MSG_INFO
, "EAP-TTLS: Short frame with TLS "
1327 eap_ttls_state(data
, FAILURE
);
1330 tls_msg_len
= (pos
[0] << 24) | (pos
[1] << 16) | (pos
[2] << 8) |
1332 wpa_printf(MSG_DEBUG
, "EAP-TTLS: TLS Message Length: %d",
1334 if (data
->ssl
.tls_in_left
== 0) {
1335 data
->ssl
.tls_in_total
= tls_msg_len
;
1336 data
->ssl
.tls_in_left
= tls_msg_len
;
1337 free(data
->ssl
.tls_in
);
1338 data
->ssl
.tls_in
= NULL
;
1339 data
->ssl
.tls_in_len
= 0;
1345 switch (data
->state
) {
1347 if (eap_tls_process_helper(sm
, &data
->ssl
, pos
, left
) < 0) {
1348 wpa_printf(MSG_INFO
, "EAP-TTLS: TLS processing "
1350 eap_ttls_state(data
, FAILURE
);
1355 case PHASE_FINISHED
:
1356 eap_ttls_process_phase2(sm
, data
, resp
, pos
, left
);
1358 case PHASE2_MSCHAPV2_RESP
:
1359 if (data
->mschapv2_resp_ok
&& left
== 0) {
1360 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Peer "
1361 "acknowledged response");
1362 eap_ttls_state(data
, data
->ttls_version
> 0 ?
1363 PHASE_FINISHED
: SUCCESS
);
1364 } else if (!data
->mschapv2_resp_ok
) {
1365 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Peer "
1366 "acknowledged error");
1367 eap_ttls_state(data
, FAILURE
);
1369 wpa_printf(MSG_DEBUG
, "EAP-TTLS/MSCHAPV2: Unexpected "
1370 "frame from peer (payload len %d, expected "
1371 "empty frame)", left
);
1372 eap_ttls_state(data
, FAILURE
);
1376 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Unexpected state %d in %s",
1377 data
->state
, __func__
);
1381 if (tls_connection_get_write_alerts(sm
->ssl_ctx
, data
->ssl
.conn
) > 1) {
1382 wpa_printf(MSG_INFO
, "EAP-TTLS: Locally detected fatal error "
1383 "in TLS processing");
1384 eap_ttls_state(data
, FAILURE
);
1389 static Boolean
eap_ttls_isDone(struct eap_sm
*sm
, void *priv
)
1391 struct eap_ttls_data
*data
= priv
;
1392 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1396 static u8
* eap_ttls_v1_derive_key(struct eap_sm
*sm
,
1397 struct eap_ttls_data
*data
)
1399 struct tls_keys keys
;
1402 memset(&keys
, 0, sizeof(keys
));
1403 if (tls_connection_get_keys(sm
->ssl_ctx
, data
->ssl
.conn
, &keys
) ||
1404 keys
.client_random
== NULL
|| keys
.server_random
== NULL
||
1405 keys
.inner_secret
== NULL
) {
1406 wpa_printf(MSG_INFO
, "EAP-TTLS: Could not get inner secret, "
1407 "client random, or server random to derive keying "
1412 rnd
= malloc(keys
.client_random_len
+ keys
.server_random_len
);
1413 key
= malloc(EAP_TLS_KEY_LEN
);
1414 if (rnd
== NULL
|| key
== NULL
) {
1415 wpa_printf(MSG_INFO
, "EAP-TTLS: No memory for key derivation");
1420 memcpy(rnd
, keys
.client_random
, keys
.client_random_len
);
1421 memcpy(rnd
+ keys
.client_random_len
, keys
.server_random
,
1422 keys
.server_random_len
);
1424 if (tls_prf(keys
.inner_secret
, keys
.inner_secret_len
,
1425 "ttls v1 keying material", rnd
, keys
.client_random_len
+
1426 keys
.server_random_len
, key
, EAP_TLS_KEY_LEN
)) {
1427 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Failed to derive key");
1433 wpa_hexdump(MSG_DEBUG
, "EAP-TTLS: client/server random",
1434 rnd
, keys
.client_random_len
+ keys
.server_random_len
);
1435 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS: TLS/IA inner secret",
1436 keys
.inner_secret
, keys
.inner_secret_len
);
1444 static u8
* eap_ttls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1446 struct eap_ttls_data
*data
= priv
;
1449 if (data
->state
!= SUCCESS
)
1452 if (data
->ttls_version
== 0) {
1453 eapKeyData
= eap_tls_derive_key(sm
, &data
->ssl
,
1454 "ttls keying material",
1457 eapKeyData
= eap_ttls_v1_derive_key(sm
, data
);
1461 *len
= EAP_TLS_KEY_LEN
;
1462 wpa_hexdump_key(MSG_DEBUG
, "EAP-TTLS: Derived key",
1463 eapKeyData
, EAP_TLS_KEY_LEN
);
1465 wpa_printf(MSG_DEBUG
, "EAP-TTLS: Failed to derive key");
1472 static Boolean
eap_ttls_isSuccess(struct eap_sm
*sm
, void *priv
)
1474 struct eap_ttls_data
*data
= priv
;
1475 return data
->state
== SUCCESS
;
1479 int eap_server_ttls_register(void)
1481 struct eap_method
*eap
;
1484 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
1485 EAP_VENDOR_IETF
, EAP_TYPE_TTLS
, "TTLS");
1489 eap
->init
= eap_ttls_init
;
1490 eap
->reset
= eap_ttls_reset
;
1491 eap
->buildReq
= eap_ttls_buildReq
;
1492 eap
->check
= eap_ttls_check
;
1493 eap
->process
= eap_ttls_process
;
1494 eap
->isDone
= eap_ttls_isDone
;
1495 eap
->getKey
= eap_ttls_getKey
;
1496 eap
->isSuccess
= eap_ttls_isSuccess
;
1498 ret
= eap_server_method_register(eap
);
1500 eap_server_method_free(eap
);