2 * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
20 #include "eap_tls_common.h"
21 #include "eap_common/eap_tlv_common.h"
22 #include "eap_common/eap_peap_common.h"
27 /* Maximum supported PEAP version
28 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
29 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
30 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
32 #define EAP_PEAP_VERSION 1
35 static void eap_peap_reset(struct eap_sm
*sm
, void *priv
);
38 struct eap_peap_data
{
39 struct eap_ssl_data ssl
;
41 START
, PHASE1
, PHASE1_ID2
, PHASE2_START
, PHASE2_ID
,
42 PHASE2_METHOD
, PHASE2_SOH
,
43 PHASE2_TLV
, SUCCESS_REQ
, FAILURE_REQ
, SUCCESS
, FAILURE
48 const struct eap_method
*phase2_method
;
51 struct wpabuf
*pending_phase2_resp
;
52 enum { TLV_REQ_NONE
, TLV_REQ_SUCCESS
, TLV_REQ_FAILURE
} tlv_request
;
53 int crypto_binding_sent
;
54 int crypto_binding_used
;
55 enum { NO_BINDING
, OPTIONAL_BINDING
, REQUIRE_BINDING
} crypto_binding
;
60 size_t phase2_key_len
;
61 struct wpabuf
*soh_response
;
65 static const char * eap_peap_state_txt(int state
)
75 return "PHASE2_START";
79 return "PHASE2_METHOD";
98 static void eap_peap_state(struct eap_peap_data
*data
, int state
)
100 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s -> %s",
101 eap_peap_state_txt(data
->state
),
102 eap_peap_state_txt(state
));
107 static struct wpabuf
* eap_peapv2_tlv_eap_payload(struct wpabuf
*buf
)
110 struct eap_tlv_hdr
*tlv
;
115 /* Encapsulate EAP packet in EAP-Payload TLV */
116 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Add EAP-Payload TLV");
117 e
= wpabuf_alloc(sizeof(*tlv
) + wpabuf_len(buf
));
119 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Failed to allocate memory "
120 "for TLV encapsulation");
124 tlv
= wpabuf_put(e
, sizeof(*tlv
));
125 tlv
->tlv_type
= host_to_be16(EAP_TLV_TYPE_MANDATORY
|
126 EAP_TLV_EAP_PAYLOAD_TLV
);
127 tlv
->length
= host_to_be16(wpabuf_len(buf
));
128 wpabuf_put_buf(e
, buf
);
134 static void eap_peap_req_success(struct eap_sm
*sm
,
135 struct eap_peap_data
*data
)
137 if (data
->state
== FAILURE
|| data
->state
== FAILURE_REQ
) {
138 eap_peap_state(data
, FAILURE
);
142 if (data
->peap_version
== 0) {
143 data
->tlv_request
= TLV_REQ_SUCCESS
;
144 eap_peap_state(data
, PHASE2_TLV
);
146 eap_peap_state(data
, SUCCESS_REQ
);
151 static void eap_peap_req_failure(struct eap_sm
*sm
,
152 struct eap_peap_data
*data
)
154 if (data
->state
== FAILURE
|| data
->state
== FAILURE_REQ
||
155 data
->state
== SUCCESS_REQ
|| data
->tlv_request
!= TLV_REQ_NONE
) {
156 eap_peap_state(data
, FAILURE
);
160 if (data
->peap_version
== 0) {
161 data
->tlv_request
= TLV_REQ_FAILURE
;
162 eap_peap_state(data
, PHASE2_TLV
);
164 eap_peap_state(data
, FAILURE_REQ
);
169 static void * eap_peap_init(struct eap_sm
*sm
)
171 struct eap_peap_data
*data
;
173 data
= os_zalloc(sizeof(*data
));
176 data
->peap_version
= EAP_PEAP_VERSION
;
177 data
->force_version
= -1;
178 if (sm
->user
&& sm
->user
->force_version
>= 0) {
179 data
->force_version
= sm
->user
->force_version
;
180 wpa_printf(MSG_DEBUG
, "EAP-PEAP: forcing version %d",
181 data
->force_version
);
182 data
->peap_version
= data
->force_version
;
185 data
->crypto_binding
= OPTIONAL_BINDING
;
187 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0)) {
188 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to initialize SSL.");
189 eap_peap_reset(sm
, data
);
197 static void eap_peap_reset(struct eap_sm
*sm
, void *priv
)
199 struct eap_peap_data
*data
= priv
;
202 if (data
->phase2_priv
&& data
->phase2_method
)
203 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
204 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
205 wpabuf_free(data
->pending_phase2_resp
);
206 os_free(data
->phase2_key
);
207 wpabuf_free(data
->soh_response
);
212 static struct wpabuf
* eap_peap_build_start(struct eap_sm
*sm
,
213 struct eap_peap_data
*data
, u8 id
)
217 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, 1,
218 EAP_CODE_REQUEST
, id
);
220 wpa_printf(MSG_ERROR
, "EAP-PEAP: Failed to allocate memory for"
222 eap_peap_state(data
, FAILURE
);
226 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
| data
->peap_version
);
228 eap_peap_state(data
, PHASE1
);
234 static struct wpabuf
* eap_peap_build_phase2_req(struct eap_sm
*sm
,
235 struct eap_peap_data
*data
,
238 struct wpabuf
*buf
, *encr_req
;
242 if (data
->phase2_method
== NULL
|| data
->phase2_priv
== NULL
) {
243 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 method not ready");
246 buf
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, id
);
247 if (data
->peap_version
>= 2 && buf
)
248 buf
= eap_peapv2_tlv_eap_payload(buf
);
252 req
= wpabuf_head(buf
);
253 req_len
= wpabuf_len(buf
);
254 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 data",
257 if (data
->peap_version
== 0 &&
258 data
->phase2_method
->method
!= EAP_TYPE_TLV
) {
259 req
+= sizeof(struct eap_hdr
);
260 req_len
-= sizeof(struct eap_hdr
);
263 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, req
, req_len
);
271 static struct wpabuf
* eap_peap_build_phase2_soh(struct eap_sm
*sm
,
272 struct eap_peap_data
*data
,
275 struct wpabuf
*buf1
, *buf
, *encr_req
;
279 buf1
= tncs_build_soh_request();
283 buf
= eap_msg_alloc(EAP_VENDOR_MICROSOFT
, 0x21, wpabuf_len(buf1
),
284 EAP_CODE_REQUEST
, id
);
289 wpabuf_put_buf(buf
, buf1
);
292 req
= wpabuf_head(buf
);
293 req_len
= wpabuf_len(buf
);
295 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 SOH data",
298 req
+= sizeof(struct eap_hdr
);
299 req_len
-= sizeof(struct eap_hdr
);
301 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, req
, req_len
);
309 static void eap_peap_get_isk(struct eap_peap_data
*data
,
310 u8
*isk
, size_t isk_len
)
314 os_memset(isk
, 0, isk_len
);
315 if (data
->phase2_key
== NULL
)
318 key_len
= data
->phase2_key_len
;
319 if (key_len
> isk_len
)
321 os_memcpy(isk
, data
->phase2_key
, key_len
);
325 static int eap_peap_derive_cmk(struct eap_sm
*sm
, struct eap_peap_data
*data
)
328 u8 isk
[32], imck
[60];
331 * Tunnel key (TK) is the first 60 octets of the key generated by
332 * phase 1 of PEAP (based on TLS).
334 tk
= eap_server_tls_derive_key(sm
, &data
->ssl
, "client EAP encryption",
338 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TK", tk
, 60);
340 eap_peap_get_isk(data
, isk
, sizeof(isk
));
341 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: ISK", isk
, sizeof(isk
));
344 * IPMK Seed = "Inner Methods Compound Keys" | ISK
345 * TempKey = First 40 octets of TK
346 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
347 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
348 * in the end of the label just before ISK; is that just a typo?)
350 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TempKey", tk
, 40);
351 peap_prfplus(data
->peap_version
, tk
, 40, "Inner Methods Compound Keys",
352 isk
, sizeof(isk
), imck
, sizeof(imck
));
353 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IMCK (IPMKj)",
358 /* TODO: fast-connect: IPMK|CMK = TK */
359 os_memcpy(data
->ipmk
, imck
, 40);
360 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IPMK (S-IPMKj)", data
->ipmk
, 40);
361 os_memcpy(data
->cmk
, imck
+ 40, 20);
362 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK (CMKj)", data
->cmk
, 20);
368 static struct wpabuf
* eap_peap_build_phase2_tlv(struct eap_sm
*sm
,
369 struct eap_peap_data
*data
,
372 struct wpabuf
*buf
, *encr_req
;
375 len
= 6; /* Result TLV */
376 if (data
->crypto_binding
!= NO_BINDING
)
377 len
+= 60; /* Cryptobinding TLV */
379 if (data
->soh_response
)
380 len
+= wpabuf_len(data
->soh_response
);
383 buf
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, len
,
384 EAP_CODE_REQUEST
, id
);
388 wpabuf_put_u8(buf
, 0x80); /* Mandatory */
389 wpabuf_put_u8(buf
, EAP_TLV_RESULT_TLV
);
391 wpabuf_put_be16(buf
, 2);
393 wpabuf_put_be16(buf
, data
->tlv_request
== TLV_REQ_SUCCESS
?
394 EAP_TLV_RESULT_SUCCESS
: EAP_TLV_RESULT_FAILURE
);
396 if (data
->peap_version
== 0 && data
->tlv_request
== TLV_REQ_SUCCESS
&&
397 data
->crypto_binding
!= NO_BINDING
) {
399 u8 eap_type
= EAP_TYPE_PEAP
;
405 if (data
->soh_response
) {
406 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Adding MS-SOH "
408 wpabuf_put_buf(buf
, data
->soh_response
);
409 wpabuf_free(data
->soh_response
);
410 data
->soh_response
= NULL
;
414 if (eap_peap_derive_cmk(sm
, data
) < 0 ||
415 os_get_random(data
->binding_nonce
, 32)) {
420 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
421 addr
[0] = wpabuf_put(buf
, 0);
426 tlv_type
= EAP_TLV_CRYPTO_BINDING_TLV
;
427 if (data
->peap_version
>= 2)
428 tlv_type
|= EAP_TLV_TYPE_MANDATORY
;
429 wpabuf_put_be16(buf
, tlv_type
);
430 wpabuf_put_be16(buf
, 56);
432 wpabuf_put_u8(buf
, 0); /* Reserved */
433 wpabuf_put_u8(buf
, data
->peap_version
); /* Version */
434 wpabuf_put_u8(buf
, data
->recv_version
); /* RecvVersion */
435 wpabuf_put_u8(buf
, 0); /* SubType: 0 = Request, 1 = Response */
436 wpabuf_put_data(buf
, data
->binding_nonce
, 32); /* Nonce */
437 mac
= wpabuf_put(buf
, 20); /* Compound_MAC */
438 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC CMK",
440 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 1",
442 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 2",
444 hmac_sha1_vector(data
->cmk
, 20, 2, addr
, len
, mac
);
445 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC",
447 data
->crypto_binding_sent
= 1;
450 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 TLV data",
453 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, wpabuf_head(buf
),
461 static struct wpabuf
* eap_peap_build_phase2_term(struct eap_sm
*sm
,
462 struct eap_peap_data
*data
,
465 struct wpabuf
*encr_req
;
469 req_len
= sizeof(*hdr
);
470 hdr
= os_zalloc(req_len
);
474 hdr
->code
= success
? EAP_CODE_SUCCESS
: EAP_CODE_FAILURE
;
475 hdr
->identifier
= id
;
476 hdr
->length
= host_to_be16(req_len
);
478 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 data",
479 (u8
*) hdr
, req_len
);
481 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, (u8
*) hdr
, req_len
);
488 static struct wpabuf
* eap_peap_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
490 struct eap_peap_data
*data
= priv
;
492 if (data
->ssl
.state
== FRAG_ACK
) {
493 return eap_server_tls_build_ack(id
, EAP_TYPE_PEAP
,
497 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
498 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_PEAP
,
499 data
->peap_version
, id
);
502 switch (data
->state
) {
504 return eap_peap_build_start(sm
, data
, id
);
507 if (data
->peap_version
< 2 &&
508 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
509 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase1 done, "
511 eap_peap_state(data
, PHASE2_START
);
516 wpabuf_free(data
->ssl
.out_buf
);
517 data
->ssl
.out_used
= 0;
518 data
->ssl
.out_buf
= eap_peap_build_phase2_req(sm
, data
, id
);
522 wpabuf_free(data
->ssl
.out_buf
);
523 data
->ssl
.out_used
= 0;
524 data
->ssl
.out_buf
= eap_peap_build_phase2_soh(sm
, data
, id
);
528 wpabuf_free(data
->ssl
.out_buf
);
529 data
->ssl
.out_used
= 0;
530 data
->ssl
.out_buf
= eap_peap_build_phase2_tlv(sm
, data
, id
);
533 wpabuf_free(data
->ssl
.out_buf
);
534 data
->ssl
.out_used
= 0;
535 data
->ssl
.out_buf
= eap_peap_build_phase2_term(sm
, data
, id
,
539 wpabuf_free(data
->ssl
.out_buf
);
540 data
->ssl
.out_used
= 0;
541 data
->ssl
.out_buf
= eap_peap_build_phase2_term(sm
, data
, id
,
545 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
546 __func__
, data
->state
);
550 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_PEAP
,
551 data
->peap_version
, id
);
555 static Boolean
eap_peap_check(struct eap_sm
*sm
, void *priv
,
556 struct wpabuf
*respData
)
561 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, respData
, &len
);
562 if (pos
== NULL
|| len
< 1) {
563 wpa_printf(MSG_INFO
, "EAP-PEAP: Invalid frame");
571 static int eap_peap_phase2_init(struct eap_sm
*sm
, struct eap_peap_data
*data
,
574 if (data
->phase2_priv
&& data
->phase2_method
) {
575 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
576 data
->phase2_method
= NULL
;
577 data
->phase2_priv
= NULL
;
579 data
->phase2_method
= eap_server_get_eap_method(EAP_VENDOR_IETF
,
581 if (!data
->phase2_method
)
585 data
->phase2_priv
= data
->phase2_method
->init(sm
);
591 static int eap_tlv_validate_cryptobinding(struct eap_sm
*sm
,
592 struct eap_peap_data
*data
,
593 const u8
*crypto_tlv
,
594 size_t crypto_tlv_len
)
596 u8 buf
[61], mac
[SHA1_MAC_LEN
];
599 if (crypto_tlv_len
!= 4 + 56) {
600 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid cryptobinding TLV "
601 "length %d", (int) crypto_tlv_len
);
606 pos
+= 4; /* TLV header */
607 if (pos
[1] != data
->peap_version
) {
608 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV Version "
609 "mismatch (was %d; expected %d)",
610 pos
[1], data
->peap_version
);
615 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected Cryptobinding TLV "
616 "SubType %d", pos
[3]);
620 pos
+= 32; /* Nonce */
622 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
623 os_memcpy(buf
, crypto_tlv
, 60);
624 os_memset(buf
+ 4 + 4 + 32, 0, 20); /* Compound_MAC */
625 buf
[60] = EAP_TYPE_PEAP
;
626 hmac_sha1(data
->cmk
, 20, buf
, sizeof(buf
), mac
);
628 if (os_memcmp(mac
, pos
, SHA1_MAC_LEN
) != 0) {
629 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid Compound_MAC in "
630 "cryptobinding TLV");
631 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK", data
->cmk
, 20);
632 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding seed data",
637 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Valid cryptobinding TLV received");
643 static void eap_peap_process_phase2_tlv(struct eap_sm
*sm
,
644 struct eap_peap_data
*data
,
645 struct wpabuf
*in_data
)
649 const u8
*result_tlv
= NULL
, *crypto_tlv
= NULL
;
650 size_t result_tlv_len
= 0, crypto_tlv_len
= 0;
651 int tlv_type
, mandatory
, tlv_len
;
653 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, in_data
, &left
);
655 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid EAP-TLV header");
660 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Received TLVs", pos
, left
);
662 mandatory
= !!(pos
[0] & 0x80);
663 tlv_type
= pos
[0] & 0x3f;
664 tlv_type
= (tlv_type
<< 8) | pos
[1];
665 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
668 if ((size_t) tlv_len
> left
) {
669 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLV underrun "
670 "(tlv_len=%d left=%lu)", tlv_len
,
671 (unsigned long) left
);
672 eap_peap_state(data
, FAILURE
);
676 case EAP_TLV_RESULT_TLV
:
678 result_tlv_len
= tlv_len
;
680 case EAP_TLV_CRYPTO_BINDING_TLV
:
682 crypto_tlv_len
= tlv_len
;
685 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported TLV Type "
687 mandatory
? " (mandatory)" : "");
689 eap_peap_state(data
, FAILURE
);
692 /* Ignore this TLV, but process other TLVs */
700 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Last TLV too short in "
701 "Request (left=%lu)", (unsigned long) left
);
702 eap_peap_state(data
, FAILURE
);
706 /* Process supported TLVs */
707 if (crypto_tlv
&& data
->crypto_binding_sent
) {
708 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV",
709 crypto_tlv
, crypto_tlv_len
);
710 if (eap_tlv_validate_cryptobinding(sm
, data
, crypto_tlv
- 4,
711 crypto_tlv_len
+ 4) < 0) {
712 eap_peap_state(data
, FAILURE
);
715 data
->crypto_binding_used
= 1;
716 } else if (!crypto_tlv
&& data
->crypto_binding_sent
&&
717 data
->crypto_binding
== REQUIRE_BINDING
) {
718 wpa_printf(MSG_DEBUG
, "EAP-PEAP: No cryptobinding TLV");
719 eap_peap_state(data
, FAILURE
);
725 const char *requested
;
727 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Result TLV",
728 result_tlv
, result_tlv_len
);
729 if (result_tlv_len
< 2) {
730 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Result TLV "
732 (unsigned long) result_tlv_len
);
733 eap_peap_state(data
, FAILURE
);
736 requested
= data
->tlv_request
== TLV_REQ_SUCCESS
? "Success" :
738 status
= WPA_GET_BE16(result_tlv
);
739 if (status
== EAP_TLV_RESULT_SUCCESS
) {
740 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Success "
741 "- requested %s", requested
);
742 if (data
->tlv_request
== TLV_REQ_SUCCESS
)
743 eap_peap_state(data
, SUCCESS
);
745 eap_peap_state(data
, FAILURE
);
747 } else if (status
== EAP_TLV_RESULT_FAILURE
) {
748 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Failure "
749 "- requested %s", requested
);
750 eap_peap_state(data
, FAILURE
);
752 wpa_printf(MSG_INFO
, "EAP-PEAP: Unknown TLV Result "
753 "Status %d", status
);
754 eap_peap_state(data
, FAILURE
);
761 static void eap_peap_process_phase2_soh(struct eap_sm
*sm
,
762 struct eap_peap_data
*data
,
763 struct wpabuf
*in_data
)
765 const u8
*pos
, *vpos
;
767 const u8
*soh_tlv
= NULL
;
768 size_t soh_tlv_len
= 0;
769 int tlv_type
, mandatory
, tlv_len
, vtlv_len
;
773 pos
= eap_hdr_validate(EAP_VENDOR_MICROSOFT
, 0x21, in_data
, &left
);
775 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Not a valid SoH EAP "
776 "Extensions Method header - skip TNC");
781 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Received TLVs (SoH)", pos
, left
);
783 mandatory
= !!(pos
[0] & 0x80);
784 tlv_type
= pos
[0] & 0x3f;
785 tlv_type
= (tlv_type
<< 8) | pos
[1];
786 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
789 if ((size_t) tlv_len
> left
) {
790 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLV underrun "
791 "(tlv_len=%d left=%lu)", tlv_len
,
792 (unsigned long) left
);
793 eap_peap_state(data
, FAILURE
);
797 case EAP_TLV_VENDOR_SPECIFIC_TLV
:
799 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Too short "
800 "vendor specific TLV (len=%d)",
802 eap_peap_state(data
, FAILURE
);
806 vendor_id
= WPA_GET_BE32(pos
);
807 if (vendor_id
!= EAP_VENDOR_MICROSOFT
) {
809 eap_peap_state(data
, FAILURE
);
816 mandatory
= !!(vpos
[0] & 0x80);
817 tlv_type
= vpos
[0] & 0x3f;
818 tlv_type
= (tlv_type
<< 8) | vpos
[1];
819 vtlv_len
= ((int) vpos
[2] << 8) | vpos
[3];
821 if (vpos
+ vtlv_len
> pos
+ left
) {
822 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Vendor TLV "
824 eap_peap_state(data
, FAILURE
);
830 soh_tlv_len
= vtlv_len
;
834 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported MS-TLV "
835 "Type %d%s", tlv_type
,
836 mandatory
? " (mandatory)" : "");
838 eap_peap_state(data
, FAILURE
);
841 /* Ignore this TLV, but process other TLVs */
844 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported TLV Type "
846 mandatory
? " (mandatory)" : "");
848 eap_peap_state(data
, FAILURE
);
851 /* Ignore this TLV, but process other TLVs */
859 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Last TLV too short in "
860 "Request (left=%lu)", (unsigned long) left
);
861 eap_peap_state(data
, FAILURE
);
865 /* Process supported TLVs */
868 wpabuf_free(data
->soh_response
);
869 data
->soh_response
= tncs_process_soh(soh_tlv
, soh_tlv_len
,
872 eap_peap_state(data
, FAILURE
);
876 wpa_printf(MSG_DEBUG
, "EAP-PEAP: No SoH TLV received");
877 eap_peap_state(data
, FAILURE
);
882 eap_peap_state(data
, PHASE2_METHOD
);
883 next_type
= sm
->user
->methods
[0].method
;
884 sm
->user_eap_method_index
= 1;
885 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d", next_type
);
886 eap_peap_phase2_init(sm
, data
, next_type
);
891 static void eap_peap_process_phase2_response(struct eap_sm
*sm
,
892 struct eap_peap_data
*data
,
893 struct wpabuf
*in_data
)
895 u8 next_type
= EAP_TYPE_NONE
;
896 const struct eap_hdr
*hdr
;
900 if (data
->state
== PHASE2_TLV
) {
901 eap_peap_process_phase2_tlv(sm
, data
, in_data
);
906 if (data
->state
== PHASE2_SOH
) {
907 eap_peap_process_phase2_soh(sm
, data
, in_data
);
912 if (data
->phase2_priv
== NULL
) {
913 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - Phase2 not "
914 "initialized?!", __func__
);
918 hdr
= wpabuf_head(in_data
);
919 pos
= (const u8
*) (hdr
+ 1);
921 if (wpabuf_len(in_data
) > sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
922 left
= wpabuf_len(in_data
) - sizeof(*hdr
);
923 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Phase2 type Nak'ed; "
924 "allowed types", pos
+ 1, left
- 1);
925 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
926 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
927 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
929 next_type
= sm
->user
->methods
[
930 sm
->user_eap_method_index
++].method
;
931 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d",
934 eap_peap_req_failure(sm
, data
);
935 next_type
= EAP_TYPE_NONE
;
937 eap_peap_phase2_init(sm
, data
, next_type
);
941 if (data
->phase2_method
->check(sm
, data
->phase2_priv
, in_data
)) {
942 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 check() asked to "
943 "ignore the packet");
947 data
->phase2_method
->process(sm
, data
->phase2_priv
, in_data
);
949 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
950 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method is in "
951 "pending wait state - save decrypted response");
952 wpabuf_free(data
->pending_phase2_resp
);
953 data
->pending_phase2_resp
= wpabuf_dup(in_data
);
956 if (!data
->phase2_method
->isDone(sm
, data
->phase2_priv
))
959 if (!data
->phase2_method
->isSuccess(sm
, data
->phase2_priv
)) {
960 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method failed");
961 eap_peap_req_failure(sm
, data
);
962 next_type
= EAP_TYPE_NONE
;
963 eap_peap_phase2_init(sm
, data
, next_type
);
967 os_free(data
->phase2_key
);
968 if (data
->phase2_method
->getKey
) {
969 data
->phase2_key
= data
->phase2_method
->getKey(
970 sm
, data
->phase2_priv
, &data
->phase2_key_len
);
971 if (data
->phase2_key
== NULL
) {
972 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 getKey "
974 eap_peap_req_failure(sm
, data
);
975 eap_peap_phase2_init(sm
, data
, EAP_TYPE_NONE
);
979 if (data
->phase2_key_len
== 32 &&
980 data
->phase2_method
->vendor
== EAP_VENDOR_IETF
&&
981 data
->phase2_method
->method
== EAP_TYPE_MSCHAPV2
) {
983 * Microsoft uses reverse order for MS-MPPE keys in
984 * EAP-PEAP when compared to EAP-FAST derivation of
985 * ISK. Swap the keys here to get the correct ISK for
986 * EAP-PEAPv0 cryptobinding.
989 os_memcpy(tmp
, data
->phase2_key
, 16);
990 os_memcpy(data
->phase2_key
, data
->phase2_key
+ 16, 16);
991 os_memcpy(data
->phase2_key
+ 16, tmp
, 16);
995 switch (data
->state
) {
999 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1000 wpa_hexdump_ascii(MSG_DEBUG
, "EAP_PEAP: Phase2 "
1001 "Identity not found in the user "
1003 sm
->identity
, sm
->identity_len
);
1004 eap_peap_req_failure(sm
, data
);
1005 next_type
= EAP_TYPE_NONE
;
1010 if (data
->state
!= PHASE2_SOH
&& sm
->tnc
&&
1011 data
->peap_version
== 0) {
1012 eap_peap_state(data
, PHASE2_SOH
);
1013 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Try to initialize "
1015 next_type
= EAP_TYPE_NONE
;
1018 #endif /* EAP_TNC */
1020 eap_peap_state(data
, PHASE2_METHOD
);
1021 next_type
= sm
->user
->methods
[0].method
;
1022 sm
->user_eap_method_index
= 1;
1023 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d", next_type
);
1026 eap_peap_req_success(sm
, data
);
1027 next_type
= EAP_TYPE_NONE
;
1032 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
1033 __func__
, data
->state
);
1037 eap_peap_phase2_init(sm
, data
, next_type
);
1041 static void eap_peap_process_phase2(struct eap_sm
*sm
,
1042 struct eap_peap_data
*data
,
1043 const struct wpabuf
*respData
,
1044 struct wpabuf
*in_buf
)
1046 struct wpabuf
*in_decrypted
;
1048 const struct eap_hdr
*hdr
;
1049 size_t buf_len
, len
;
1053 in_data
= wpabuf_mhead(in_buf
);
1054 in_len
= wpabuf_len(in_buf
);
1056 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received %lu bytes encrypted data for"
1057 " Phase 2", (unsigned long) in_len
);
1059 if (data
->pending_phase2_resp
) {
1060 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Pending Phase 2 response - "
1061 "skip decryption and use old data");
1062 eap_peap_process_phase2_response(sm
, data
,
1063 data
->pending_phase2_resp
);
1064 wpabuf_free(data
->pending_phase2_resp
);
1065 data
->pending_phase2_resp
= NULL
;
1071 * Even though we try to disable TLS compression, it is possible that
1072 * this cannot be done with all TLS libraries. Add extra buffer space
1073 * to handle the possibility of the decrypted data being longer than
1078 in_decrypted
= wpabuf_alloc(buf_len
);
1079 if (in_decrypted
== NULL
) {
1080 wpa_printf(MSG_WARNING
, "EAP-PEAP: failed to allocate memory "
1085 len_decrypted
= tls_connection_decrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1087 wpabuf_mhead(in_decrypted
),
1089 if (len_decrypted
< 0) {
1090 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to decrypt Phase 2 "
1092 wpabuf_free(in_decrypted
);
1093 eap_peap_state(data
, FAILURE
);
1096 wpabuf_put(in_decrypted
, len_decrypted
);
1098 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Decrypted Phase 2 EAP",
1101 hdr
= wpabuf_head(in_decrypted
);
1103 if (data
->peap_version
== 0 && data
->state
!= PHASE2_TLV
) {
1104 const struct eap_hdr
*resp
;
1105 struct eap_hdr
*nhdr
;
1106 struct wpabuf
*nbuf
=
1107 wpabuf_alloc(sizeof(struct eap_hdr
) +
1108 wpabuf_len(in_decrypted
));
1110 wpabuf_free(in_decrypted
);
1114 resp
= wpabuf_head(respData
);
1115 nhdr
= wpabuf_put(nbuf
, sizeof(*nhdr
));
1116 nhdr
->code
= resp
->code
;
1117 nhdr
->identifier
= resp
->identifier
;
1118 nhdr
->length
= host_to_be16(sizeof(struct eap_hdr
) +
1119 wpabuf_len(in_decrypted
));
1120 wpabuf_put_buf(nbuf
, in_decrypted
);
1121 wpabuf_free(in_decrypted
);
1123 in_decrypted
= nbuf
;
1124 } else if (data
->peap_version
>= 2) {
1125 struct eap_tlv_hdr
*tlv
;
1126 struct wpabuf
*nmsg
;
1128 if (wpabuf_len(in_decrypted
) < sizeof(*tlv
) + sizeof(*hdr
)) {
1129 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Too short Phase 2 "
1131 wpabuf_free(in_decrypted
);
1134 tlv
= wpabuf_mhead(in_decrypted
);
1135 if ((be_to_host16(tlv
->tlv_type
) & EAP_TLV_TYPE_MASK
) !=
1136 EAP_TLV_EAP_PAYLOAD_TLV
) {
1137 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Not an EAP TLV");
1138 wpabuf_free(in_decrypted
);
1141 if (sizeof(*tlv
) + be_to_host16(tlv
->length
) >
1142 wpabuf_len(in_decrypted
)) {
1143 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Invalid EAP TLV "
1145 wpabuf_free(in_decrypted
);
1148 hdr
= (struct eap_hdr
*) (tlv
+ 1);
1149 if (be_to_host16(hdr
->length
) > be_to_host16(tlv
->length
)) {
1150 wpa_printf(MSG_INFO
, "EAP-PEAPv2: No room for full "
1151 "EAP packet in EAP TLV");
1152 wpabuf_free(in_decrypted
);
1156 nmsg
= wpabuf_alloc(be_to_host16(hdr
->length
));
1158 wpabuf_free(in_decrypted
);
1162 wpabuf_put_data(nmsg
, hdr
, be_to_host16(hdr
->length
));
1163 wpabuf_free(in_decrypted
);
1164 in_decrypted
= nmsg
;
1167 hdr
= wpabuf_head(in_decrypted
);
1168 if (wpabuf_len(in_decrypted
) < (int) sizeof(*hdr
)) {
1169 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Phase 2 "
1170 "EAP frame (len=%lu)",
1171 (unsigned long) wpabuf_len(in_decrypted
));
1172 wpabuf_free(in_decrypted
);
1173 eap_peap_req_failure(sm
, data
);
1176 len
= be_to_host16(hdr
->length
);
1177 if (len
> wpabuf_len(in_decrypted
)) {
1178 wpa_printf(MSG_INFO
, "EAP-PEAP: Length mismatch in "
1179 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1180 (unsigned long) wpabuf_len(in_decrypted
),
1181 (unsigned long) len
);
1182 wpabuf_free(in_decrypted
);
1183 eap_peap_req_failure(sm
, data
);
1186 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received Phase 2: code=%d "
1187 "identifier=%d length=%lu", hdr
->code
, hdr
->identifier
,
1188 (unsigned long) len
);
1189 switch (hdr
->code
) {
1190 case EAP_CODE_RESPONSE
:
1191 eap_peap_process_phase2_response(sm
, data
, in_decrypted
);
1193 case EAP_CODE_SUCCESS
:
1194 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Success");
1195 if (data
->state
== SUCCESS_REQ
) {
1196 eap_peap_state(data
, SUCCESS
);
1199 case EAP_CODE_FAILURE
:
1200 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Failure");
1201 eap_peap_state(data
, FAILURE
);
1204 wpa_printf(MSG_INFO
, "EAP-PEAP: Unexpected code=%d in "
1205 "Phase 2 EAP header", hdr
->code
);
1209 os_free(in_decrypted
);
1213 static int eap_peapv2_start_phase2(struct eap_sm
*sm
,
1214 struct eap_peap_data
*data
)
1216 struct wpabuf
*buf
, *buf2
;
1219 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1220 "payload in the same message");
1221 eap_peap_state(data
, PHASE1_ID2
);
1222 if (eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
))
1225 /* TODO: which Id to use here? */
1226 buf
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, 6);
1230 buf2
= eap_peapv2_tlv_eap_payload(buf
);
1234 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Identity Request", buf2
);
1236 buf
= wpabuf_alloc(data
->ssl
.tls_out_limit
);
1242 res
= tls_connection_encrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1243 wpabuf_head(buf2
), wpabuf_len(buf2
),
1245 data
->ssl
.tls_out_limit
);
1249 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1255 wpabuf_put(buf
, res
);
1256 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Encrypted Identity Request",
1259 /* Append TLS data into the pending buffer after the Server Finished */
1260 if (wpabuf_resize(&data
->ssl
.out_buf
, wpabuf_len(buf
)) < 0) {
1264 wpabuf_put_buf(data
->ssl
.out_buf
, buf
);
1271 static int eap_peap_process_version(struct eap_sm
*sm
, void *priv
,
1274 struct eap_peap_data
*data
= priv
;
1276 data
->recv_version
= peer_version
;
1277 if (data
->force_version
>= 0 && peer_version
!= data
->force_version
) {
1278 wpa_printf(MSG_INFO
, "EAP-PEAP: peer did not select the forced"
1279 " version (forced=%d peer=%d) - reject",
1280 data
->force_version
, peer_version
);
1283 if (peer_version
< data
->peap_version
) {
1284 wpa_printf(MSG_DEBUG
, "EAP-PEAP: peer ver=%d, own ver=%d; "
1286 peer_version
, data
->peap_version
, peer_version
);
1287 data
->peap_version
= peer_version
;
1294 static void eap_peap_process_msg(struct eap_sm
*sm
, void *priv
,
1295 const struct wpabuf
*respData
)
1297 struct eap_peap_data
*data
= priv
;
1299 switch (data
->state
) {
1301 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0) {
1302 eap_peap_state(data
, FAILURE
);
1306 if (data
->peap_version
>= 2 &&
1307 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1308 if (eap_peapv2_start_phase2(sm
, data
)) {
1309 eap_peap_state(data
, FAILURE
);
1315 eap_peap_state(data
, PHASE2_ID
);
1316 eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
);
1323 eap_peap_process_phase2(sm
, data
, respData
, data
->ssl
.in_buf
);
1326 eap_peap_state(data
, SUCCESS
);
1329 eap_peap_state(data
, FAILURE
);
1332 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected state %d in %s",
1333 data
->state
, __func__
);
1339 static void eap_peap_process(struct eap_sm
*sm
, void *priv
,
1340 struct wpabuf
*respData
)
1342 struct eap_peap_data
*data
= priv
;
1343 if (eap_server_tls_process(sm
, &data
->ssl
, respData
, data
,
1344 EAP_TYPE_PEAP
, eap_peap_process_version
,
1345 eap_peap_process_msg
) < 0)
1346 eap_peap_state(data
, FAILURE
);
1350 static Boolean
eap_peap_isDone(struct eap_sm
*sm
, void *priv
)
1352 struct eap_peap_data
*data
= priv
;
1353 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1357 static u8
* eap_peap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1359 struct eap_peap_data
*data
= priv
;
1362 if (data
->state
!= SUCCESS
)
1365 if (data
->crypto_binding_used
) {
1368 * Note: It looks like Microsoft implementation requires null
1369 * termination for this label while the one used for deriving
1370 * IPMK|CMK did not use null termination.
1372 peap_prfplus(data
->peap_version
, data
->ipmk
, 40,
1373 "Session Key Generating Function",
1374 (u8
*) "\00", 1, csk
, sizeof(csk
));
1375 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CSK", csk
, sizeof(csk
));
1376 eapKeyData
= os_malloc(EAP_TLS_KEY_LEN
);
1378 os_memcpy(eapKeyData
, csk
, EAP_TLS_KEY_LEN
);
1379 *len
= EAP_TLS_KEY_LEN
;
1380 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1381 eapKeyData
, EAP_TLS_KEY_LEN
);
1383 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive "
1390 /* TODO: PEAPv1 - different label in some cases */
1391 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
1392 "client EAP encryption",
1395 *len
= EAP_TLS_KEY_LEN
;
1396 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1397 eapKeyData
, EAP_TLS_KEY_LEN
);
1399 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive key");
1406 static Boolean
eap_peap_isSuccess(struct eap_sm
*sm
, void *priv
)
1408 struct eap_peap_data
*data
= priv
;
1409 return data
->state
== SUCCESS
;
1413 int eap_server_peap_register(void)
1415 struct eap_method
*eap
;
1418 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
1419 EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, "PEAP");
1423 eap
->init
= eap_peap_init
;
1424 eap
->reset
= eap_peap_reset
;
1425 eap
->buildReq
= eap_peap_buildReq
;
1426 eap
->check
= eap_peap_check
;
1427 eap
->process
= eap_peap_process
;
1428 eap
->isDone
= eap_peap_isDone
;
1429 eap
->getKey
= eap_peap_getKey
;
1430 eap
->isSuccess
= eap_peap_isSuccess
;
1432 ret
= eap_server_method_register(eap
);
1434 eap_server_method_free(eap
);