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"
25 /* Maximum supported PEAP version
26 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
27 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
28 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
30 #define EAP_PEAP_VERSION 1
33 static void eap_peap_reset(struct eap_sm
*sm
, void *priv
);
36 struct eap_peap_data
{
37 struct eap_ssl_data ssl
;
39 START
, PHASE1
, PHASE1_ID2
, PHASE2_START
, PHASE2_ID
,
41 PHASE2_TLV
, SUCCESS_REQ
, FAILURE_REQ
, SUCCESS
, FAILURE
46 const struct eap_method
*phase2_method
;
49 struct wpabuf
*pending_phase2_resp
;
50 enum { TLV_REQ_NONE
, TLV_REQ_SUCCESS
, TLV_REQ_FAILURE
} tlv_request
;
51 int crypto_binding_sent
;
52 int crypto_binding_used
;
53 enum { NO_BINDING
, OPTIONAL_BINDING
, REQUIRE_BINDING
} crypto_binding
;
58 size_t phase2_key_len
;
62 static const char * eap_peap_state_txt(int state
)
72 return "PHASE2_START";
76 return "PHASE2_METHOD";
93 static void eap_peap_state(struct eap_peap_data
*data
, int state
)
95 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s -> %s",
96 eap_peap_state_txt(data
->state
),
97 eap_peap_state_txt(state
));
102 static struct wpabuf
* eap_peapv2_tlv_eap_payload(struct wpabuf
*buf
)
105 struct eap_tlv_hdr
*tlv
;
110 /* Encapsulate EAP packet in EAP-Payload TLV */
111 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Add EAP-Payload TLV");
112 e
= wpabuf_alloc(sizeof(*tlv
) + wpabuf_len(buf
));
114 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Failed to allocate memory "
115 "for TLV encapsulation");
119 tlv
= wpabuf_put(e
, sizeof(*tlv
));
120 tlv
->tlv_type
= host_to_be16(EAP_TLV_TYPE_MANDATORY
|
121 EAP_TLV_EAP_PAYLOAD_TLV
);
122 tlv
->length
= host_to_be16(wpabuf_len(buf
));
123 wpabuf_put_buf(e
, buf
);
129 static void eap_peap_req_success(struct eap_sm
*sm
,
130 struct eap_peap_data
*data
)
132 if (data
->state
== FAILURE
|| data
->state
== FAILURE_REQ
) {
133 eap_peap_state(data
, FAILURE
);
137 if (data
->peap_version
== 0) {
138 data
->tlv_request
= TLV_REQ_SUCCESS
;
139 eap_peap_state(data
, PHASE2_TLV
);
141 eap_peap_state(data
, SUCCESS_REQ
);
146 static void eap_peap_req_failure(struct eap_sm
*sm
,
147 struct eap_peap_data
*data
)
149 if (data
->state
== FAILURE
|| data
->state
== FAILURE_REQ
||
150 data
->state
== SUCCESS_REQ
|| data
->tlv_request
!= TLV_REQ_NONE
) {
151 eap_peap_state(data
, FAILURE
);
155 if (data
->peap_version
== 0) {
156 data
->tlv_request
= TLV_REQ_FAILURE
;
157 eap_peap_state(data
, PHASE2_TLV
);
159 eap_peap_state(data
, FAILURE_REQ
);
164 static void * eap_peap_init(struct eap_sm
*sm
)
166 struct eap_peap_data
*data
;
168 data
= os_zalloc(sizeof(*data
));
171 data
->peap_version
= EAP_PEAP_VERSION
;
172 data
->force_version
= -1;
173 if (sm
->user
&& sm
->user
->force_version
>= 0) {
174 data
->force_version
= sm
->user
->force_version
;
175 wpa_printf(MSG_DEBUG
, "EAP-PEAP: forcing version %d",
176 data
->force_version
);
177 data
->peap_version
= data
->force_version
;
180 data
->crypto_binding
= OPTIONAL_BINDING
;
182 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0)) {
183 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to initialize SSL.");
184 eap_peap_reset(sm
, data
);
192 static void eap_peap_reset(struct eap_sm
*sm
, void *priv
)
194 struct eap_peap_data
*data
= priv
;
197 if (data
->phase2_priv
&& data
->phase2_method
)
198 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
199 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
200 wpabuf_free(data
->pending_phase2_resp
);
201 os_free(data
->phase2_key
);
206 static struct wpabuf
* eap_peap_build_start(struct eap_sm
*sm
,
207 struct eap_peap_data
*data
, u8 id
)
211 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, 1,
212 EAP_CODE_REQUEST
, id
);
214 wpa_printf(MSG_ERROR
, "EAP-PEAP: Failed to allocate memory for"
216 eap_peap_state(data
, FAILURE
);
220 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
| data
->peap_version
);
222 eap_peap_state(data
, PHASE1
);
228 static struct wpabuf
* eap_peap_build_req(struct eap_sm
*sm
,
229 struct eap_peap_data
*data
, u8 id
)
234 res
= eap_server_tls_buildReq_helper(sm
, &data
->ssl
, EAP_TYPE_PEAP
,
235 data
->peap_version
, id
, &req
);
237 if (data
->peap_version
< 2 &&
238 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
239 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase1 done, starting "
241 eap_peap_state(data
, PHASE2_START
);
245 return eap_server_tls_build_ack(id
, EAP_TYPE_PEAP
,
251 static struct wpabuf
* eap_peap_encrypt(struct eap_sm
*sm
,
252 struct eap_peap_data
*data
,
253 u8 id
, const u8
*plain
,
259 /* TODO: add support for fragmentation, if needed. This will need to
260 * add TLS Message Length field, if the frame is fragmented. */
261 buf
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
,
262 1 + data
->ssl
.tls_out_limit
,
263 EAP_CODE_REQUEST
, id
);
267 wpabuf_put_u8(buf
, data
->peap_version
);
269 res
= tls_connection_encrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
270 plain
, plain_len
, wpabuf_put(buf
, 0),
271 data
->ssl
.tls_out_limit
);
273 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to encrypt Phase 2 "
279 wpabuf_put(buf
, res
);
286 static struct wpabuf
* eap_peap_build_phase2_req(struct eap_sm
*sm
,
287 struct eap_peap_data
*data
,
290 struct wpabuf
*buf
, *encr_req
;
294 buf
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, id
);
295 if (data
->peap_version
>= 2 && buf
)
296 buf
= eap_peapv2_tlv_eap_payload(buf
);
300 req
= wpabuf_head(buf
);
301 req_len
= wpabuf_len(buf
);
302 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 data",
305 if (data
->peap_version
== 0 &&
306 data
->phase2_method
->method
!= EAP_TYPE_TLV
) {
307 req
+= sizeof(struct eap_hdr
);
308 req_len
-= sizeof(struct eap_hdr
);
311 encr_req
= eap_peap_encrypt(sm
, data
, id
, req
, req_len
);
318 static void eap_peap_get_isk(struct eap_peap_data
*data
,
319 u8
*isk
, size_t isk_len
)
323 os_memset(isk
, 0, isk_len
);
324 if (data
->phase2_key
== NULL
)
327 key_len
= data
->phase2_key_len
;
328 if (key_len
> isk_len
)
330 os_memcpy(isk
, data
->phase2_key
, key_len
);
334 void peap_prfplus(int version
, const u8
*key
, size_t key_len
,
335 const char *label
, const u8
*seed
, size_t seed_len
,
336 u8
*buf
, size_t buf_len
)
338 unsigned char counter
= 0;
340 u8 hash
[SHA1_MAC_LEN
];
341 size_t label_len
= os_strlen(label
);
343 const unsigned char *addr
[5];
348 addr
[1] = (unsigned char *) label
;
355 * PRF+(K, S, LEN) = T1 | T2 | ... | Tn
356 * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00)
357 * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00)
359 * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00)
371 * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where:
372 * T1 = HMAC-SHA1(K, S | LEN | 0x01)
373 * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02)
374 * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03)
375 * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04)
379 extra
[0] = buf_len
& 0xff;
388 while (pos
< buf_len
) {
390 plen
= buf_len
- pos
;
391 hmac_sha1_vector(key
, key_len
, 5, addr
, len
, hash
);
392 if (plen
>= SHA1_MAC_LEN
) {
393 os_memcpy(&buf
[pos
], hash
, SHA1_MAC_LEN
);
396 os_memcpy(&buf
[pos
], hash
, plen
);
399 len
[0] = SHA1_MAC_LEN
;
404 static int eap_peap_derive_cmk(struct eap_sm
*sm
, struct eap_peap_data
*data
)
407 u8 isk
[32], imck
[60];
410 * Tunnel key (TK) is the first 60 octets of the key generated by
411 * phase 1 of PEAP (based on TLS).
413 tk
= eap_server_tls_derive_key(sm
, &data
->ssl
, "client EAP encryption",
417 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TK", tk
, 60);
419 eap_peap_get_isk(data
, isk
, sizeof(isk
));
420 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: ISK", isk
, sizeof(isk
));
423 * IPMK Seed = "Inner Methods Compound Keys" | ISK
424 * TempKey = First 40 octets of TK
425 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
426 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
427 * in the end of the label just before ISK; is that just a typo?)
429 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TempKey", tk
, 40);
430 peap_prfplus(data
->peap_version
, tk
, 40, "Inner Methods Compound Keys",
431 isk
, sizeof(isk
), imck
, sizeof(imck
));
432 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IMCK (IPMKj)",
437 /* TODO: fast-connect: IPMK|CMK = TK */
438 os_memcpy(data
->ipmk
, imck
, 40);
439 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IPMK (S-IPMKj)", data
->ipmk
, 40);
440 os_memcpy(data
->cmk
, imck
+ 40, 20);
441 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK (CMKj)", data
->cmk
, 20);
447 static struct wpabuf
* eap_peap_build_phase2_tlv(struct eap_sm
*sm
,
448 struct eap_peap_data
*data
,
451 struct wpabuf
*buf
, *encr_req
;
454 len
= 6; /* Result TLV */
455 if (data
->crypto_binding
!= NO_BINDING
)
456 len
+= 60; /* Cryptobinding TLV */
458 buf
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, len
,
459 EAP_CODE_REQUEST
, id
);
463 wpabuf_put_u8(buf
, 0x80); /* Mandatory */
464 wpabuf_put_u8(buf
, EAP_TLV_RESULT_TLV
);
466 wpabuf_put_be16(buf
, 2);
468 wpabuf_put_be16(buf
, data
->tlv_request
== TLV_REQ_SUCCESS
?
469 EAP_TLV_RESULT_SUCCESS
: EAP_TLV_RESULT_FAILURE
);
471 if (data
->peap_version
== 0 && data
->tlv_request
== TLV_REQ_SUCCESS
&&
472 data
->crypto_binding
!= NO_BINDING
) {
474 u8 eap_type
= EAP_TYPE_PEAP
;
479 if (eap_peap_derive_cmk(sm
, data
) < 0 ||
480 os_get_random(data
->binding_nonce
, 32)) {
485 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
486 addr
[0] = wpabuf_put(buf
, 0);
491 tlv_type
= EAP_TLV_CRYPTO_BINDING_TLV
;
492 if (data
->peap_version
>= 2)
493 tlv_type
|= EAP_TLV_TYPE_MANDATORY
;
494 wpabuf_put_be16(buf
, tlv_type
);
495 wpabuf_put_be16(buf
, 56);
497 wpabuf_put_u8(buf
, 0); /* Reserved */
498 wpabuf_put_u8(buf
, data
->peap_version
); /* Version */
499 wpabuf_put_u8(buf
, data
->recv_version
); /* RecvVersion */
500 wpabuf_put_u8(buf
, 0); /* SubType: 0 = Request, 1 = Response */
501 wpabuf_put_data(buf
, data
->binding_nonce
, 32); /* Nonce */
502 mac
= wpabuf_put(buf
, 20); /* Compound_MAC */
503 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC CMK",
505 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 1",
507 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 2",
509 hmac_sha1_vector(data
->cmk
, 20, 2, addr
, len
, mac
);
510 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC",
512 data
->crypto_binding_sent
= 1;
515 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 TLV data",
518 encr_req
= eap_peap_encrypt(sm
, data
, id
, wpabuf_head(buf
),
526 static struct wpabuf
* eap_peap_build_phase2_term(struct eap_sm
*sm
,
527 struct eap_peap_data
*data
,
530 struct wpabuf
*encr_req
;
534 req_len
= sizeof(*hdr
);
535 hdr
= os_zalloc(req_len
);
539 hdr
->code
= success
? EAP_CODE_SUCCESS
: EAP_CODE_FAILURE
;
540 hdr
->identifier
= id
;
541 hdr
->length
= host_to_be16(req_len
);
543 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 data",
544 (u8
*) hdr
, req_len
);
546 encr_req
= eap_peap_encrypt(sm
, data
, id
, (u8
*) hdr
, req_len
);
553 static struct wpabuf
* eap_peap_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
555 struct eap_peap_data
*data
= priv
;
557 switch (data
->state
) {
559 return eap_peap_build_start(sm
, data
, id
);
562 return eap_peap_build_req(sm
, data
, id
);
565 return eap_peap_build_phase2_req(sm
, data
, id
);
567 return eap_peap_build_phase2_tlv(sm
, data
, id
);
569 return eap_peap_build_phase2_term(sm
, data
, id
, 1);
571 return eap_peap_build_phase2_term(sm
, data
, id
, 0);
573 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
574 __func__
, data
->state
);
580 static Boolean
eap_peap_check(struct eap_sm
*sm
, void *priv
,
581 struct wpabuf
*respData
)
586 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, respData
, &len
);
587 if (pos
== NULL
|| len
< 1) {
588 wpa_printf(MSG_INFO
, "EAP-PEAP: Invalid frame");
596 static int eap_peap_phase2_init(struct eap_sm
*sm
, struct eap_peap_data
*data
,
599 if (data
->phase2_priv
&& data
->phase2_method
) {
600 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
601 data
->phase2_method
= NULL
;
602 data
->phase2_priv
= NULL
;
604 data
->phase2_method
= eap_server_get_eap_method(EAP_VENDOR_IETF
,
606 if (!data
->phase2_method
)
610 data
->phase2_priv
= data
->phase2_method
->init(sm
);
616 static int eap_tlv_validate_cryptobinding(struct eap_sm
*sm
,
617 struct eap_peap_data
*data
,
618 const u8
*crypto_tlv
,
619 size_t crypto_tlv_len
)
621 u8 buf
[61], mac
[SHA1_MAC_LEN
];
624 if (crypto_tlv_len
!= 4 + 56) {
625 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid cryptobinding TLV "
626 "length %d", (int) crypto_tlv_len
);
631 pos
+= 4; /* TLV header */
632 if (pos
[1] != data
->peap_version
) {
633 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV Version "
634 "mismatch (was %d; expected %d)",
635 pos
[1], data
->peap_version
);
640 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected Cryptobinding TLV "
641 "SubType %d", pos
[3]);
645 pos
+= 32; /* Nonce */
647 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
648 os_memcpy(buf
, crypto_tlv
, 60);
649 os_memset(buf
+ 4 + 4 + 32, 0, 20); /* Compound_MAC */
650 buf
[60] = EAP_TYPE_PEAP
;
651 hmac_sha1(data
->cmk
, 20, buf
, sizeof(buf
), mac
);
653 if (os_memcmp(mac
, pos
, SHA1_MAC_LEN
) != 0) {
654 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid Compound_MAC in "
655 "cryptobinding TLV");
656 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK", data
->cmk
, 20);
657 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding seed data",
662 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Valid cryptobinding TLV received");
668 static void eap_peap_process_phase2_tlv(struct eap_sm
*sm
,
669 struct eap_peap_data
*data
,
670 struct wpabuf
*in_data
)
674 const u8
*result_tlv
= NULL
, *crypto_tlv
= NULL
;
675 size_t result_tlv_len
= 0, crypto_tlv_len
= 0;
676 int tlv_type
, mandatory
, tlv_len
;
678 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, in_data
, &left
);
680 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid EAP-TLV header");
685 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Received TLVs", pos
, left
);
687 mandatory
= !!(pos
[0] & 0x80);
688 tlv_type
= pos
[0] & 0x3f;
689 tlv_type
= (tlv_type
<< 8) | pos
[1];
690 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
693 if ((size_t) tlv_len
> left
) {
694 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLV underrun "
695 "(tlv_len=%d left=%lu)", tlv_len
,
696 (unsigned long) left
);
697 eap_peap_state(data
, FAILURE
);
701 case EAP_TLV_RESULT_TLV
:
703 result_tlv_len
= tlv_len
;
705 case EAP_TLV_CRYPTO_BINDING_TLV
:
707 crypto_tlv_len
= tlv_len
;
710 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported TLV Type "
712 mandatory
? " (mandatory)" : "");
714 eap_peap_state(data
, FAILURE
);
717 /* Ignore this TLV, but process other TLVs */
725 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Last TLV too short in "
726 "Request (left=%lu)", (unsigned long) left
);
727 eap_peap_state(data
, FAILURE
);
731 /* Process supported TLVs */
732 if (crypto_tlv
&& data
->crypto_binding_sent
) {
733 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV",
734 crypto_tlv
, crypto_tlv_len
);
735 if (eap_tlv_validate_cryptobinding(sm
, data
, crypto_tlv
- 4,
736 crypto_tlv_len
+ 4) < 0) {
737 eap_peap_state(data
, FAILURE
);
740 data
->crypto_binding_used
= 1;
741 } else if (!crypto_tlv
&& data
->crypto_binding_sent
&&
742 data
->crypto_binding
== REQUIRE_BINDING
) {
743 wpa_printf(MSG_DEBUG
, "EAP-PEAP: No cryptobinding TLV");
744 eap_peap_state(data
, FAILURE
);
750 const char *requested
;
752 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Result TLV",
753 result_tlv
, result_tlv_len
);
754 if (result_tlv_len
< 2) {
755 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Result TLV "
757 (unsigned long) result_tlv_len
);
758 eap_peap_state(data
, FAILURE
);
761 requested
= data
->tlv_request
== TLV_REQ_SUCCESS
? "Success" :
763 status
= WPA_GET_BE16(result_tlv
);
764 if (status
== EAP_TLV_RESULT_SUCCESS
) {
765 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Success "
766 "- requested %s", requested
);
767 if (data
->tlv_request
== TLV_REQ_SUCCESS
)
768 eap_peap_state(data
, SUCCESS
);
770 eap_peap_state(data
, FAILURE
);
772 } else if (status
== EAP_TLV_RESULT_FAILURE
) {
773 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Failure "
774 "- requested %s", requested
);
775 eap_peap_state(data
, FAILURE
);
777 wpa_printf(MSG_INFO
, "EAP-PEAP: Unknown TLV Result "
778 "Status %d", status
);
779 eap_peap_state(data
, FAILURE
);
785 static void eap_peap_process_phase2_response(struct eap_sm
*sm
,
786 struct eap_peap_data
*data
,
787 struct wpabuf
*in_data
)
789 u8 next_type
= EAP_TYPE_NONE
;
790 const struct eap_hdr
*hdr
;
794 if (data
->state
== PHASE2_TLV
) {
795 eap_peap_process_phase2_tlv(sm
, data
, in_data
);
799 if (data
->phase2_priv
== NULL
) {
800 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - Phase2 not "
801 "initialized?!", __func__
);
805 hdr
= wpabuf_head(in_data
);
806 pos
= (const u8
*) (hdr
+ 1);
808 if (wpabuf_len(in_data
) > sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
809 left
= wpabuf_len(in_data
) - sizeof(*hdr
);
810 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Phase2 type Nak'ed; "
811 "allowed types", pos
+ 1, left
- 1);
812 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
813 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
814 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
816 next_type
= sm
->user
->methods
[
817 sm
->user_eap_method_index
++].method
;
818 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d",
821 eap_peap_req_failure(sm
, data
);
822 next_type
= EAP_TYPE_NONE
;
824 eap_peap_phase2_init(sm
, data
, next_type
);
828 if (data
->phase2_method
->check(sm
, data
->phase2_priv
, in_data
)) {
829 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 check() asked to "
830 "ignore the packet");
834 data
->phase2_method
->process(sm
, data
->phase2_priv
, in_data
);
836 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
837 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method is in "
838 "pending wait state - save decrypted response");
839 wpabuf_free(data
->pending_phase2_resp
);
840 data
->pending_phase2_resp
= wpabuf_dup(in_data
);
843 if (!data
->phase2_method
->isDone(sm
, data
->phase2_priv
))
846 if (!data
->phase2_method
->isSuccess(sm
, data
->phase2_priv
)) {
847 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method failed");
848 eap_peap_req_failure(sm
, data
);
849 next_type
= EAP_TYPE_NONE
;
850 eap_peap_phase2_init(sm
, data
, next_type
);
854 os_free(data
->phase2_key
);
855 if (data
->phase2_method
->getKey
) {
856 data
->phase2_key
= data
->phase2_method
->getKey(
857 sm
, data
->phase2_priv
, &data
->phase2_key_len
);
858 if (data
->phase2_key
== NULL
) {
859 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 getKey "
861 eap_peap_req_failure(sm
, data
);
862 eap_peap_phase2_init(sm
, data
, EAP_TYPE_NONE
);
866 if (data
->phase2_key_len
== 32 &&
867 data
->phase2_method
->vendor
== EAP_VENDOR_IETF
&&
868 data
->phase2_method
->method
== EAP_TYPE_MSCHAPV2
) {
870 * Microsoft uses reverse order for MS-MPPE keys in
871 * EAP-PEAP when compared to EAP-FAST derivation of
872 * ISK. Swap the keys here to get the correct ISK for
873 * EAP-PEAPv0 cryptobinding.
876 os_memcpy(tmp
, data
->phase2_key
, 16);
877 os_memcpy(data
->phase2_key
, data
->phase2_key
+ 16, 16);
878 os_memcpy(data
->phase2_key
+ 16, tmp
, 16);
882 switch (data
->state
) {
885 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
886 wpa_hexdump_ascii(MSG_DEBUG
, "EAP_PEAP: Phase2 "
887 "Identity not found in the user "
889 sm
->identity
, sm
->identity_len
);
890 eap_peap_req_failure(sm
, data
);
891 next_type
= EAP_TYPE_NONE
;
895 eap_peap_state(data
, PHASE2_METHOD
);
896 next_type
= sm
->user
->methods
[0].method
;
897 sm
->user_eap_method_index
= 1;
898 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d", next_type
);
901 eap_peap_req_success(sm
, data
);
902 next_type
= EAP_TYPE_NONE
;
907 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
908 __func__
, data
->state
);
912 eap_peap_phase2_init(sm
, data
, next_type
);
916 static void eap_peap_process_phase2(struct eap_sm
*sm
,
917 struct eap_peap_data
*data
,
918 const struct wpabuf
*respData
,
919 const u8
*in_data
, size_t in_len
)
921 struct wpabuf
*in_decrypted
;
922 int len_decrypted
, res
;
923 const struct eap_hdr
*hdr
;
926 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received %lu bytes encrypted data for"
927 " Phase 2", (unsigned long) in_len
);
929 if (data
->pending_phase2_resp
) {
930 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Pending Phase 2 response - "
931 "skip decryption and use old data");
932 eap_peap_process_phase2_response(sm
, data
,
933 data
->pending_phase2_resp
);
934 wpabuf_free(data
->pending_phase2_resp
);
935 data
->pending_phase2_resp
= NULL
;
939 /* FIX: get rid of const -> non-const typecast */
940 res
= eap_server_tls_data_reassemble(sm
, &data
->ssl
, (u8
**) &in_data
,
942 if (res
< 0 || res
== 1)
946 if (data
->ssl
.tls_in_total
> buf_len
)
947 buf_len
= data
->ssl
.tls_in_total
;
948 in_decrypted
= wpabuf_alloc(buf_len
);
949 if (in_decrypted
== NULL
) {
950 os_free(data
->ssl
.tls_in
);
951 data
->ssl
.tls_in
= NULL
;
952 data
->ssl
.tls_in_len
= 0;
953 wpa_printf(MSG_WARNING
, "EAP-PEAP: failed to allocate memory "
958 len_decrypted
= tls_connection_decrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
960 wpabuf_mhead(in_decrypted
),
962 os_free(data
->ssl
.tls_in
);
963 data
->ssl
.tls_in
= NULL
;
964 data
->ssl
.tls_in_len
= 0;
965 if (len_decrypted
< 0) {
966 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to decrypt Phase 2 "
968 wpabuf_free(in_decrypted
);
969 eap_peap_state(data
, FAILURE
);
972 wpabuf_put(in_decrypted
, len_decrypted
);
974 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Decrypted Phase 2 EAP",
977 hdr
= wpabuf_head(in_decrypted
);
979 if (data
->peap_version
== 0 && data
->state
!= PHASE2_TLV
) {
980 const struct eap_hdr
*resp
;
981 struct eap_hdr
*nhdr
;
982 struct wpabuf
*nbuf
=
983 wpabuf_alloc(sizeof(struct eap_hdr
) +
984 wpabuf_len(in_decrypted
));
986 wpabuf_free(in_decrypted
);
990 resp
= wpabuf_head(respData
);
991 nhdr
= wpabuf_put(nbuf
, sizeof(*nhdr
));
992 nhdr
->code
= resp
->code
;
993 nhdr
->identifier
= resp
->identifier
;
994 nhdr
->length
= host_to_be16(sizeof(struct eap_hdr
) +
995 wpabuf_len(in_decrypted
));
996 wpabuf_put_buf(nbuf
, in_decrypted
);
997 wpabuf_free(in_decrypted
);
1000 } else if (data
->peap_version
>= 2) {
1001 struct eap_tlv_hdr
*tlv
;
1002 struct wpabuf
*nmsg
;
1004 if (wpabuf_len(in_decrypted
) < sizeof(*tlv
) + sizeof(*hdr
)) {
1005 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Too short Phase 2 "
1007 wpabuf_free(in_decrypted
);
1010 tlv
= wpabuf_mhead(in_decrypted
);
1011 if ((be_to_host16(tlv
->tlv_type
) & EAP_TLV_TYPE_MASK
) !=
1012 EAP_TLV_EAP_PAYLOAD_TLV
) {
1013 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Not an EAP TLV");
1014 wpabuf_free(in_decrypted
);
1017 if (sizeof(*tlv
) + be_to_host16(tlv
->length
) >
1018 wpabuf_len(in_decrypted
)) {
1019 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Invalid EAP TLV "
1021 wpabuf_free(in_decrypted
);
1024 hdr
= (struct eap_hdr
*) (tlv
+ 1);
1025 if (be_to_host16(hdr
->length
) > be_to_host16(tlv
->length
)) {
1026 wpa_printf(MSG_INFO
, "EAP-PEAPv2: No room for full "
1027 "EAP packet in EAP TLV");
1028 wpabuf_free(in_decrypted
);
1032 nmsg
= wpabuf_alloc(be_to_host16(hdr
->length
));
1034 wpabuf_free(in_decrypted
);
1038 wpabuf_put_data(nmsg
, hdr
, be_to_host16(hdr
->length
));
1039 wpabuf_free(in_decrypted
);
1040 in_decrypted
= nmsg
;
1043 hdr
= wpabuf_head(in_decrypted
);
1044 if (wpabuf_len(in_decrypted
) < (int) sizeof(*hdr
)) {
1045 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Phase 2 "
1046 "EAP frame (len=%lu)",
1047 (unsigned long) wpabuf_len(in_decrypted
));
1048 wpabuf_free(in_decrypted
);
1049 eap_peap_req_failure(sm
, data
);
1052 len
= be_to_host16(hdr
->length
);
1053 if (len
> wpabuf_len(in_decrypted
)) {
1054 wpa_printf(MSG_INFO
, "EAP-PEAP: Length mismatch in "
1055 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1056 (unsigned long) wpabuf_len(in_decrypted
),
1057 (unsigned long) len
);
1058 wpabuf_free(in_decrypted
);
1059 eap_peap_req_failure(sm
, data
);
1062 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received Phase 2: code=%d "
1063 "identifier=%d length=%lu", hdr
->code
, hdr
->identifier
,
1064 (unsigned long) len
);
1065 switch (hdr
->code
) {
1066 case EAP_CODE_RESPONSE
:
1067 eap_peap_process_phase2_response(sm
, data
, in_decrypted
);
1069 case EAP_CODE_SUCCESS
:
1070 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Success");
1071 if (data
->state
== SUCCESS_REQ
) {
1072 eap_peap_state(data
, SUCCESS
);
1075 case EAP_CODE_FAILURE
:
1076 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Failure");
1077 eap_peap_state(data
, FAILURE
);
1080 wpa_printf(MSG_INFO
, "EAP-PEAP: Unexpected code=%d in "
1081 "Phase 2 EAP header", hdr
->code
);
1085 os_free(in_decrypted
);
1089 static int eap_peapv2_start_phase2(struct eap_sm
*sm
,
1090 struct eap_peap_data
*data
)
1092 struct wpabuf
*buf
, *buf2
;
1096 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1097 "payload in the same message");
1098 eap_peap_state(data
, PHASE1_ID2
);
1099 if (eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
))
1102 /* TODO: which Id to use here? */
1103 buf
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, 6);
1107 buf2
= eap_peapv2_tlv_eap_payload(buf
);
1111 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Identity Request", buf2
);
1113 buf
= wpabuf_alloc(data
->ssl
.tls_out_limit
);
1119 res
= tls_connection_encrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1120 wpabuf_head(buf2
), wpabuf_len(buf2
),
1122 data
->ssl
.tls_out_limit
);
1126 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1132 wpabuf_put(buf
, res
);
1133 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Encrypted Identity Request",
1136 /* Append TLS data into the pending buffer after the Server Finished */
1137 tls_out
= os_realloc(data
->ssl
.tls_out
,
1138 data
->ssl
.tls_out_len
+ wpabuf_len(buf
));
1139 if (tls_out
== NULL
) {
1144 os_memcpy(tls_out
+ data
->ssl
.tls_out_len
, wpabuf_head(buf
),
1146 data
->ssl
.tls_out
= tls_out
;
1147 data
->ssl
.tls_out_len
+= wpabuf_len(buf
);
1155 static void eap_peap_process(struct eap_sm
*sm
, void *priv
,
1156 struct wpabuf
*respData
)
1158 struct eap_peap_data
*data
= priv
;
1162 unsigned int tls_msg_len
;
1165 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, respData
,
1167 if (pos
== NULL
|| left
< 1)
1171 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Received packet(len=%lu) - "
1172 "Flags 0x%02x", (unsigned long) wpabuf_len(respData
),
1174 data
->recv_version
= peer_version
= flags
& EAP_PEAP_VERSION_MASK
;
1175 if (data
->force_version
>= 0 && peer_version
!= data
->force_version
) {
1176 wpa_printf(MSG_INFO
, "EAP-PEAP: peer did not select the forced"
1177 " version (forced=%d peer=%d) - reject",
1178 data
->force_version
, peer_version
);
1179 eap_peap_state(data
, FAILURE
);
1182 if (peer_version
< data
->peap_version
) {
1183 wpa_printf(MSG_DEBUG
, "EAP-PEAP: peer ver=%d, own ver=%d; "
1185 peer_version
, data
->peap_version
, peer_version
);
1186 data
->peap_version
= peer_version
;
1188 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
1190 wpa_printf(MSG_INFO
, "EAP-PEAP: Short frame with TLS "
1192 eap_peap_state(data
, FAILURE
);
1195 tls_msg_len
= WPA_GET_BE32(pos
);
1196 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLS Message Length: %d",
1198 if (data
->ssl
.tls_in_left
== 0) {
1199 data
->ssl
.tls_in_total
= tls_msg_len
;
1200 data
->ssl
.tls_in_left
= tls_msg_len
;
1201 os_free(data
->ssl
.tls_in
);
1202 data
->ssl
.tls_in
= NULL
;
1203 data
->ssl
.tls_in_len
= 0;
1209 switch (data
->state
) {
1211 if (eap_server_tls_process_helper(sm
, &data
->ssl
, pos
, left
) <
1213 wpa_printf(MSG_INFO
, "EAP-PEAP: TLS processing "
1215 eap_peap_state(data
, FAILURE
);
1219 if (data
->peap_version
>= 2 &&
1220 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1221 if (eap_peapv2_start_phase2(sm
, data
)) {
1222 eap_peap_state(data
, FAILURE
);
1228 eap_peap_state(data
, PHASE2_ID
);
1229 eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
);
1235 eap_peap_process_phase2(sm
, data
, respData
, pos
, left
);
1238 eap_peap_state(data
, SUCCESS
);
1241 eap_peap_state(data
, FAILURE
);
1244 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected state %d in %s",
1245 data
->state
, __func__
);
1249 if (tls_connection_get_write_alerts(sm
->ssl_ctx
, data
->ssl
.conn
) > 1) {
1250 wpa_printf(MSG_INFO
, "EAP-PEAP: Locally detected fatal error "
1251 "in TLS processing");
1252 eap_peap_state(data
, FAILURE
);
1257 static Boolean
eap_peap_isDone(struct eap_sm
*sm
, void *priv
)
1259 struct eap_peap_data
*data
= priv
;
1260 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1264 static u8
* eap_peap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1266 struct eap_peap_data
*data
= priv
;
1269 if (data
->state
!= SUCCESS
)
1272 if (data
->crypto_binding_used
) {
1275 * Note: It looks like Microsoft implementation requires null
1276 * termination for this label while the one used for deriving
1277 * IPMK|CMK did not use null termination.
1279 peap_prfplus(data
->peap_version
, data
->ipmk
, 40,
1280 "Session Key Generating Function",
1281 (u8
*) "\00", 1, csk
, sizeof(csk
));
1282 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CSK", csk
, sizeof(csk
));
1283 eapKeyData
= os_malloc(EAP_TLS_KEY_LEN
);
1285 os_memcpy(eapKeyData
, csk
, EAP_TLS_KEY_LEN
);
1286 *len
= EAP_TLS_KEY_LEN
;
1287 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1288 eapKeyData
, EAP_TLS_KEY_LEN
);
1290 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive "
1297 /* TODO: PEAPv1 - different label in some cases */
1298 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
1299 "client EAP encryption",
1302 *len
= EAP_TLS_KEY_LEN
;
1303 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1304 eapKeyData
, EAP_TLS_KEY_LEN
);
1306 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive key");
1313 static Boolean
eap_peap_isSuccess(struct eap_sm
*sm
, void *priv
)
1315 struct eap_peap_data
*data
= priv
;
1316 return data
->state
== SUCCESS
;
1320 int eap_server_peap_register(void)
1322 struct eap_method
*eap
;
1325 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
1326 EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, "PEAP");
1330 eap
->init
= eap_peap_init
;
1331 eap
->reset
= eap_peap_reset
;
1332 eap
->buildReq
= eap_peap_buildReq
;
1333 eap
->check
= eap_peap_check
;
1334 eap
->process
= eap_peap_process
;
1335 eap
->isDone
= eap_peap_isDone
;
1336 eap
->getKey
= eap_peap_getKey
;
1337 eap
->isSuccess
= eap_peap_isSuccess
;
1339 ret
= eap_server_method_register(eap
);
1341 eap_server_method_free(eap
);