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.
18 #include "crypto/sha1.h"
19 #include "crypto/tls.h"
21 #include "eap_tls_common.h"
22 #include "eap_common/eap_tlv_common.h"
23 #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
, msgbuf
;
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 wpabuf_set(&msgbuf
, req
, req_len
);
264 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, &msgbuf
);
271 #ifdef EAP_SERVER_TNC
272 static struct wpabuf
* eap_peap_build_phase2_soh(struct eap_sm
*sm
,
273 struct eap_peap_data
*data
,
276 struct wpabuf
*buf1
, *buf
, *encr_req
, msgbuf
;
280 buf1
= tncs_build_soh_request();
284 buf
= eap_msg_alloc(EAP_VENDOR_MICROSOFT
, 0x21, wpabuf_len(buf1
),
285 EAP_CODE_REQUEST
, id
);
290 wpabuf_put_buf(buf
, buf1
);
293 req
= wpabuf_head(buf
);
294 req_len
= wpabuf_len(buf
);
296 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 SOH data",
299 req
+= sizeof(struct eap_hdr
);
300 req_len
-= sizeof(struct eap_hdr
);
301 wpabuf_set(&msgbuf
, req
, req_len
);
303 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, &msgbuf
);
308 #endif /* EAP_SERVER_TNC */
311 static void eap_peap_get_isk(struct eap_peap_data
*data
,
312 u8
*isk
, size_t isk_len
)
316 os_memset(isk
, 0, isk_len
);
317 if (data
->phase2_key
== NULL
)
320 key_len
= data
->phase2_key_len
;
321 if (key_len
> isk_len
)
323 os_memcpy(isk
, data
->phase2_key
, key_len
);
327 static int eap_peap_derive_cmk(struct eap_sm
*sm
, struct eap_peap_data
*data
)
330 u8 isk
[32], imck
[60];
333 * Tunnel key (TK) is the first 60 octets of the key generated by
334 * phase 1 of PEAP (based on TLS).
336 tk
= eap_server_tls_derive_key(sm
, &data
->ssl
, "client EAP encryption",
340 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TK", tk
, 60);
342 eap_peap_get_isk(data
, isk
, sizeof(isk
));
343 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: ISK", isk
, sizeof(isk
));
346 * IPMK Seed = "Inner Methods Compound Keys" | ISK
347 * TempKey = First 40 octets of TK
348 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
349 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
350 * in the end of the label just before ISK; is that just a typo?)
352 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: TempKey", tk
, 40);
353 peap_prfplus(data
->peap_version
, tk
, 40, "Inner Methods Compound Keys",
354 isk
, sizeof(isk
), imck
, sizeof(imck
));
355 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IMCK (IPMKj)",
360 /* TODO: fast-connect: IPMK|CMK = TK */
361 os_memcpy(data
->ipmk
, imck
, 40);
362 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: IPMK (S-IPMKj)", data
->ipmk
, 40);
363 os_memcpy(data
->cmk
, imck
+ 40, 20);
364 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK (CMKj)", data
->cmk
, 20);
370 static struct wpabuf
* eap_peap_build_phase2_tlv(struct eap_sm
*sm
,
371 struct eap_peap_data
*data
,
374 struct wpabuf
*buf
, *encr_req
;
377 mlen
= 6; /* Result TLV */
378 if (data
->crypto_binding
!= NO_BINDING
)
379 mlen
+= 60; /* Cryptobinding TLV */
380 #ifdef EAP_SERVER_TNC
381 if (data
->soh_response
)
382 mlen
+= wpabuf_len(data
->soh_response
);
383 #endif /* EAP_SERVER_TNC */
385 buf
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, mlen
,
386 EAP_CODE_REQUEST
, id
);
390 wpabuf_put_u8(buf
, 0x80); /* Mandatory */
391 wpabuf_put_u8(buf
, EAP_TLV_RESULT_TLV
);
393 wpabuf_put_be16(buf
, 2);
395 wpabuf_put_be16(buf
, data
->tlv_request
== TLV_REQ_SUCCESS
?
396 EAP_TLV_RESULT_SUCCESS
: EAP_TLV_RESULT_FAILURE
);
398 if (data
->peap_version
== 0 && data
->tlv_request
== TLV_REQ_SUCCESS
&&
399 data
->crypto_binding
!= NO_BINDING
) {
401 u8 eap_type
= EAP_TYPE_PEAP
;
406 #ifdef EAP_SERVER_TNC
407 if (data
->soh_response
) {
408 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Adding MS-SOH "
410 wpabuf_put_buf(buf
, data
->soh_response
);
411 wpabuf_free(data
->soh_response
);
412 data
->soh_response
= NULL
;
414 #endif /* EAP_SERVER_TNC */
416 if (eap_peap_derive_cmk(sm
, data
) < 0 ||
417 os_get_random(data
->binding_nonce
, 32)) {
422 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
423 addr
[0] = wpabuf_put(buf
, 0);
428 tlv_type
= EAP_TLV_CRYPTO_BINDING_TLV
;
429 if (data
->peap_version
>= 2)
430 tlv_type
|= EAP_TLV_TYPE_MANDATORY
;
431 wpabuf_put_be16(buf
, tlv_type
);
432 wpabuf_put_be16(buf
, 56);
434 wpabuf_put_u8(buf
, 0); /* Reserved */
435 wpabuf_put_u8(buf
, data
->peap_version
); /* Version */
436 wpabuf_put_u8(buf
, data
->recv_version
); /* RecvVersion */
437 wpabuf_put_u8(buf
, 0); /* SubType: 0 = Request, 1 = Response */
438 wpabuf_put_data(buf
, data
->binding_nonce
, 32); /* Nonce */
439 mac
= wpabuf_put(buf
, 20); /* Compound_MAC */
440 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC CMK",
442 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 1",
444 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC data 2",
446 hmac_sha1_vector(data
->cmk
, 20, 2, addr
, len
, mac
);
447 wpa_hexdump(MSG_MSGDUMP
, "EAP-PEAP: Compound_MAC",
449 data
->crypto_binding_sent
= 1;
452 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 TLV data",
455 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, buf
);
462 static struct wpabuf
* eap_peap_build_phase2_term(struct eap_sm
*sm
,
463 struct eap_peap_data
*data
,
466 struct wpabuf
*encr_req
, msgbuf
;
470 req_len
= sizeof(*hdr
);
471 hdr
= os_zalloc(req_len
);
475 hdr
->code
= success
? EAP_CODE_SUCCESS
: EAP_CODE_FAILURE
;
476 hdr
->identifier
= id
;
477 hdr
->length
= host_to_be16(req_len
);
479 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: Encrypting Phase 2 data",
480 (u8
*) hdr
, req_len
);
482 wpabuf_set(&msgbuf
, hdr
, req_len
);
483 encr_req
= eap_server_tls_encrypt(sm
, &data
->ssl
, &msgbuf
);
490 static struct wpabuf
* eap_peap_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
492 struct eap_peap_data
*data
= priv
;
494 if (data
->ssl
.state
== FRAG_ACK
) {
495 return eap_server_tls_build_ack(id
, EAP_TYPE_PEAP
,
499 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
500 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_PEAP
,
501 data
->peap_version
, id
);
504 switch (data
->state
) {
506 return eap_peap_build_start(sm
, data
, id
);
509 if (data
->peap_version
< 2 &&
510 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
511 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase1 done, "
513 eap_peap_state(data
, PHASE2_START
);
518 wpabuf_free(data
->ssl
.tls_out
);
519 data
->ssl
.tls_out_pos
= 0;
520 data
->ssl
.tls_out
= eap_peap_build_phase2_req(sm
, data
, id
);
522 #ifdef EAP_SERVER_TNC
524 wpabuf_free(data
->ssl
.tls_out
);
525 data
->ssl
.tls_out_pos
= 0;
526 data
->ssl
.tls_out
= eap_peap_build_phase2_soh(sm
, data
, id
);
528 #endif /* EAP_SERVER_TNC */
530 wpabuf_free(data
->ssl
.tls_out
);
531 data
->ssl
.tls_out_pos
= 0;
532 data
->ssl
.tls_out
= eap_peap_build_phase2_tlv(sm
, data
, id
);
535 wpabuf_free(data
->ssl
.tls_out
);
536 data
->ssl
.tls_out_pos
= 0;
537 data
->ssl
.tls_out
= eap_peap_build_phase2_term(sm
, data
, id
,
541 wpabuf_free(data
->ssl
.tls_out
);
542 data
->ssl
.tls_out_pos
= 0;
543 data
->ssl
.tls_out
= eap_peap_build_phase2_term(sm
, data
, id
,
547 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
548 __func__
, data
->state
);
552 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_PEAP
,
553 data
->peap_version
, id
);
557 static Boolean
eap_peap_check(struct eap_sm
*sm
, void *priv
,
558 struct wpabuf
*respData
)
563 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, respData
, &len
);
564 if (pos
== NULL
|| len
< 1) {
565 wpa_printf(MSG_INFO
, "EAP-PEAP: Invalid frame");
573 static int eap_peap_phase2_init(struct eap_sm
*sm
, struct eap_peap_data
*data
,
576 if (data
->phase2_priv
&& data
->phase2_method
) {
577 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
578 data
->phase2_method
= NULL
;
579 data
->phase2_priv
= NULL
;
581 data
->phase2_method
= eap_server_get_eap_method(EAP_VENDOR_IETF
,
583 if (!data
->phase2_method
)
587 data
->phase2_priv
= data
->phase2_method
->init(sm
);
593 static int eap_tlv_validate_cryptobinding(struct eap_sm
*sm
,
594 struct eap_peap_data
*data
,
595 const u8
*crypto_tlv
,
596 size_t crypto_tlv_len
)
598 u8 buf
[61], mac
[SHA1_MAC_LEN
];
601 if (crypto_tlv_len
!= 4 + 56) {
602 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid cryptobinding TLV "
603 "length %d", (int) crypto_tlv_len
);
608 pos
+= 4; /* TLV header */
609 if (pos
[1] != data
->peap_version
) {
610 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV Version "
611 "mismatch (was %d; expected %d)",
612 pos
[1], data
->peap_version
);
617 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected Cryptobinding TLV "
618 "SubType %d", pos
[3]);
622 pos
+= 32; /* Nonce */
624 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
625 os_memcpy(buf
, crypto_tlv
, 60);
626 os_memset(buf
+ 4 + 4 + 32, 0, 20); /* Compound_MAC */
627 buf
[60] = EAP_TYPE_PEAP
;
628 hmac_sha1(data
->cmk
, 20, buf
, sizeof(buf
), mac
);
630 if (os_memcmp(mac
, pos
, SHA1_MAC_LEN
) != 0) {
631 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid Compound_MAC in "
632 "cryptobinding TLV");
633 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CMK", data
->cmk
, 20);
634 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding seed data",
639 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Valid cryptobinding TLV received");
645 static void eap_peap_process_phase2_tlv(struct eap_sm
*sm
,
646 struct eap_peap_data
*data
,
647 struct wpabuf
*in_data
)
651 const u8
*result_tlv
= NULL
, *crypto_tlv
= NULL
;
652 size_t result_tlv_len
= 0, crypto_tlv_len
= 0;
653 int tlv_type
, mandatory
, tlv_len
;
655 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TLV
, in_data
, &left
);
657 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Invalid EAP-TLV header");
662 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Received TLVs", pos
, left
);
664 mandatory
= !!(pos
[0] & 0x80);
665 tlv_type
= pos
[0] & 0x3f;
666 tlv_type
= (tlv_type
<< 8) | pos
[1];
667 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
670 if ((size_t) tlv_len
> left
) {
671 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLV underrun "
672 "(tlv_len=%d left=%lu)", tlv_len
,
673 (unsigned long) left
);
674 eap_peap_state(data
, FAILURE
);
678 case EAP_TLV_RESULT_TLV
:
680 result_tlv_len
= tlv_len
;
682 case EAP_TLV_CRYPTO_BINDING_TLV
:
684 crypto_tlv_len
= tlv_len
;
687 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported TLV Type "
689 mandatory
? " (mandatory)" : "");
691 eap_peap_state(data
, FAILURE
);
694 /* Ignore this TLV, but process other TLVs */
702 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Last TLV too short in "
703 "Request (left=%lu)", (unsigned long) left
);
704 eap_peap_state(data
, FAILURE
);
708 /* Process supported TLVs */
709 if (crypto_tlv
&& data
->crypto_binding_sent
) {
710 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Cryptobinding TLV",
711 crypto_tlv
, crypto_tlv_len
);
712 if (eap_tlv_validate_cryptobinding(sm
, data
, crypto_tlv
- 4,
713 crypto_tlv_len
+ 4) < 0) {
714 eap_peap_state(data
, FAILURE
);
717 data
->crypto_binding_used
= 1;
718 } else if (!crypto_tlv
&& data
->crypto_binding_sent
&&
719 data
->crypto_binding
== REQUIRE_BINDING
) {
720 wpa_printf(MSG_DEBUG
, "EAP-PEAP: No cryptobinding TLV");
721 eap_peap_state(data
, FAILURE
);
727 const char *requested
;
729 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Result TLV",
730 result_tlv
, result_tlv_len
);
731 if (result_tlv_len
< 2) {
732 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Result TLV "
734 (unsigned long) result_tlv_len
);
735 eap_peap_state(data
, FAILURE
);
738 requested
= data
->tlv_request
== TLV_REQ_SUCCESS
? "Success" :
740 status
= WPA_GET_BE16(result_tlv
);
741 if (status
== EAP_TLV_RESULT_SUCCESS
) {
742 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Success "
743 "- requested %s", requested
);
744 if (data
->tlv_request
== TLV_REQ_SUCCESS
)
745 eap_peap_state(data
, SUCCESS
);
747 eap_peap_state(data
, FAILURE
);
749 } else if (status
== EAP_TLV_RESULT_FAILURE
) {
750 wpa_printf(MSG_INFO
, "EAP-PEAP: TLV Result - Failure "
751 "- requested %s", requested
);
752 eap_peap_state(data
, FAILURE
);
754 wpa_printf(MSG_INFO
, "EAP-PEAP: Unknown TLV Result "
755 "Status %d", status
);
756 eap_peap_state(data
, FAILURE
);
762 #ifdef EAP_SERVER_TNC
763 static void eap_peap_process_phase2_soh(struct eap_sm
*sm
,
764 struct eap_peap_data
*data
,
765 struct wpabuf
*in_data
)
767 const u8
*pos
, *vpos
;
769 const u8
*soh_tlv
= NULL
;
770 size_t soh_tlv_len
= 0;
771 int tlv_type
, mandatory
, tlv_len
, vtlv_len
;
775 pos
= eap_hdr_validate(EAP_VENDOR_MICROSOFT
, 0x21, in_data
, &left
);
777 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Not a valid SoH EAP "
778 "Extensions Method header - skip TNC");
783 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Received TLVs (SoH)", pos
, left
);
785 mandatory
= !!(pos
[0] & 0x80);
786 tlv_type
= pos
[0] & 0x3f;
787 tlv_type
= (tlv_type
<< 8) | pos
[1];
788 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
791 if ((size_t) tlv_len
> left
) {
792 wpa_printf(MSG_DEBUG
, "EAP-PEAP: TLV underrun "
793 "(tlv_len=%d left=%lu)", tlv_len
,
794 (unsigned long) left
);
795 eap_peap_state(data
, FAILURE
);
799 case EAP_TLV_VENDOR_SPECIFIC_TLV
:
801 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Too short "
802 "vendor specific TLV (len=%d)",
804 eap_peap_state(data
, FAILURE
);
808 vendor_id
= WPA_GET_BE32(pos
);
809 if (vendor_id
!= EAP_VENDOR_MICROSOFT
) {
811 eap_peap_state(data
, FAILURE
);
818 mandatory
= !!(vpos
[0] & 0x80);
819 tlv_type
= vpos
[0] & 0x3f;
820 tlv_type
= (tlv_type
<< 8) | vpos
[1];
821 vtlv_len
= ((int) vpos
[2] << 8) | vpos
[3];
823 if (vpos
+ vtlv_len
> pos
+ left
) {
824 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Vendor TLV "
826 eap_peap_state(data
, FAILURE
);
832 soh_tlv_len
= vtlv_len
;
836 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported MS-TLV "
837 "Type %d%s", tlv_type
,
838 mandatory
? " (mandatory)" : "");
840 eap_peap_state(data
, FAILURE
);
843 /* Ignore this TLV, but process other TLVs */
846 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unsupported TLV Type "
848 mandatory
? " (mandatory)" : "");
850 eap_peap_state(data
, FAILURE
);
853 /* Ignore this TLV, but process other TLVs */
861 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Last TLV too short in "
862 "Request (left=%lu)", (unsigned long) left
);
863 eap_peap_state(data
, FAILURE
);
867 /* Process supported TLVs */
870 wpabuf_free(data
->soh_response
);
871 data
->soh_response
= tncs_process_soh(soh_tlv
, soh_tlv_len
,
874 eap_peap_state(data
, FAILURE
);
878 wpa_printf(MSG_DEBUG
, "EAP-PEAP: No SoH TLV received");
879 eap_peap_state(data
, FAILURE
);
884 eap_peap_state(data
, PHASE2_METHOD
);
885 next_type
= sm
->user
->methods
[0].method
;
886 sm
->user_eap_method_index
= 1;
887 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d", next_type
);
888 eap_peap_phase2_init(sm
, data
, next_type
);
890 #endif /* EAP_SERVER_TNC */
893 static void eap_peap_process_phase2_response(struct eap_sm
*sm
,
894 struct eap_peap_data
*data
,
895 struct wpabuf
*in_data
)
897 u8 next_type
= EAP_TYPE_NONE
;
898 const struct eap_hdr
*hdr
;
902 if (data
->state
== PHASE2_TLV
) {
903 eap_peap_process_phase2_tlv(sm
, data
, in_data
);
907 #ifdef EAP_SERVER_TNC
908 if (data
->state
== PHASE2_SOH
) {
909 eap_peap_process_phase2_soh(sm
, data
, in_data
);
912 #endif /* EAP_SERVER_TNC */
914 if (data
->phase2_priv
== NULL
) {
915 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - Phase2 not "
916 "initialized?!", __func__
);
920 hdr
= wpabuf_head(in_data
);
921 pos
= (const u8
*) (hdr
+ 1);
923 if (wpabuf_len(in_data
) > sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
924 left
= wpabuf_len(in_data
) - sizeof(*hdr
);
925 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Phase2 type Nak'ed; "
926 "allowed types", pos
+ 1, left
- 1);
927 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
928 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
929 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
931 next_type
= sm
->user
->methods
[
932 sm
->user_eap_method_index
++].method
;
933 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d",
936 eap_peap_req_failure(sm
, data
);
937 next_type
= EAP_TYPE_NONE
;
939 eap_peap_phase2_init(sm
, data
, next_type
);
943 if (data
->phase2_method
->check(sm
, data
->phase2_priv
, in_data
)) {
944 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 check() asked to "
945 "ignore the packet");
949 data
->phase2_method
->process(sm
, data
->phase2_priv
, in_data
);
951 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
952 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method is in "
953 "pending wait state - save decrypted response");
954 wpabuf_free(data
->pending_phase2_resp
);
955 data
->pending_phase2_resp
= wpabuf_dup(in_data
);
958 if (!data
->phase2_method
->isDone(sm
, data
->phase2_priv
))
961 if (!data
->phase2_method
->isSuccess(sm
, data
->phase2_priv
)) {
962 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 method failed");
963 eap_peap_req_failure(sm
, data
);
964 next_type
= EAP_TYPE_NONE
;
965 eap_peap_phase2_init(sm
, data
, next_type
);
969 os_free(data
->phase2_key
);
970 if (data
->phase2_method
->getKey
) {
971 data
->phase2_key
= data
->phase2_method
->getKey(
972 sm
, data
->phase2_priv
, &data
->phase2_key_len
);
973 if (data
->phase2_key
== NULL
) {
974 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase2 getKey "
976 eap_peap_req_failure(sm
, data
);
977 eap_peap_phase2_init(sm
, data
, EAP_TYPE_NONE
);
982 switch (data
->state
) {
986 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
987 wpa_hexdump_ascii(MSG_DEBUG
, "EAP_PEAP: Phase2 "
988 "Identity not found in the user "
990 sm
->identity
, sm
->identity_len
);
991 eap_peap_req_failure(sm
, data
);
992 next_type
= EAP_TYPE_NONE
;
996 #ifdef EAP_SERVER_TNC
997 if (data
->state
!= PHASE2_SOH
&& sm
->tnc
&&
998 data
->peap_version
== 0) {
999 eap_peap_state(data
, PHASE2_SOH
);
1000 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Try to initialize "
1002 next_type
= EAP_TYPE_NONE
;
1005 #endif /* EAP_SERVER_TNC */
1007 eap_peap_state(data
, PHASE2_METHOD
);
1008 next_type
= sm
->user
->methods
[0].method
;
1009 sm
->user_eap_method_index
= 1;
1010 wpa_printf(MSG_DEBUG
, "EAP-PEAP: try EAP type %d", next_type
);
1013 eap_peap_req_success(sm
, data
);
1014 next_type
= EAP_TYPE_NONE
;
1019 wpa_printf(MSG_DEBUG
, "EAP-PEAP: %s - unexpected state %d",
1020 __func__
, data
->state
);
1024 eap_peap_phase2_init(sm
, data
, next_type
);
1028 static void eap_peap_process_phase2(struct eap_sm
*sm
,
1029 struct eap_peap_data
*data
,
1030 const struct wpabuf
*respData
,
1031 struct wpabuf
*in_buf
)
1033 struct wpabuf
*in_decrypted
;
1034 const struct eap_hdr
*hdr
;
1037 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received %lu bytes encrypted data for"
1038 " Phase 2", (unsigned long) wpabuf_len(in_buf
));
1040 if (data
->pending_phase2_resp
) {
1041 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Pending Phase 2 response - "
1042 "skip decryption and use old data");
1043 eap_peap_process_phase2_response(sm
, data
,
1044 data
->pending_phase2_resp
);
1045 wpabuf_free(data
->pending_phase2_resp
);
1046 data
->pending_phase2_resp
= NULL
;
1050 in_decrypted
= tls_connection_decrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1052 if (in_decrypted
== NULL
) {
1053 wpa_printf(MSG_INFO
, "EAP-PEAP: Failed to decrypt Phase 2 "
1055 eap_peap_state(data
, FAILURE
);
1059 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-PEAP: Decrypted Phase 2 EAP",
1062 hdr
= wpabuf_head(in_decrypted
);
1064 if (data
->peap_version
== 0 && data
->state
!= PHASE2_TLV
) {
1065 const struct eap_hdr
*resp
;
1066 struct eap_hdr
*nhdr
;
1067 struct wpabuf
*nbuf
=
1068 wpabuf_alloc(sizeof(struct eap_hdr
) +
1069 wpabuf_len(in_decrypted
));
1071 wpabuf_free(in_decrypted
);
1075 resp
= wpabuf_head(respData
);
1076 nhdr
= wpabuf_put(nbuf
, sizeof(*nhdr
));
1077 nhdr
->code
= resp
->code
;
1078 nhdr
->identifier
= resp
->identifier
;
1079 nhdr
->length
= host_to_be16(sizeof(struct eap_hdr
) +
1080 wpabuf_len(in_decrypted
));
1081 wpabuf_put_buf(nbuf
, in_decrypted
);
1082 wpabuf_free(in_decrypted
);
1084 in_decrypted
= nbuf
;
1085 } else if (data
->peap_version
>= 2) {
1086 struct eap_tlv_hdr
*tlv
;
1087 struct wpabuf
*nmsg
;
1089 if (wpabuf_len(in_decrypted
) < sizeof(*tlv
) + sizeof(*hdr
)) {
1090 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Too short Phase 2 "
1092 wpabuf_free(in_decrypted
);
1095 tlv
= wpabuf_mhead(in_decrypted
);
1096 if ((be_to_host16(tlv
->tlv_type
) & EAP_TLV_TYPE_MASK
) !=
1097 EAP_TLV_EAP_PAYLOAD_TLV
) {
1098 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Not an EAP TLV");
1099 wpabuf_free(in_decrypted
);
1102 if (sizeof(*tlv
) + be_to_host16(tlv
->length
) >
1103 wpabuf_len(in_decrypted
)) {
1104 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Invalid EAP TLV "
1106 wpabuf_free(in_decrypted
);
1109 hdr
= (struct eap_hdr
*) (tlv
+ 1);
1110 if (be_to_host16(hdr
->length
) > be_to_host16(tlv
->length
)) {
1111 wpa_printf(MSG_INFO
, "EAP-PEAPv2: No room for full "
1112 "EAP packet in EAP TLV");
1113 wpabuf_free(in_decrypted
);
1117 nmsg
= wpabuf_alloc(be_to_host16(hdr
->length
));
1119 wpabuf_free(in_decrypted
);
1123 wpabuf_put_data(nmsg
, hdr
, be_to_host16(hdr
->length
));
1124 wpabuf_free(in_decrypted
);
1125 in_decrypted
= nmsg
;
1128 hdr
= wpabuf_head(in_decrypted
);
1129 if (wpabuf_len(in_decrypted
) < (int) sizeof(*hdr
)) {
1130 wpa_printf(MSG_INFO
, "EAP-PEAP: Too short Phase 2 "
1131 "EAP frame (len=%lu)",
1132 (unsigned long) wpabuf_len(in_decrypted
));
1133 wpabuf_free(in_decrypted
);
1134 eap_peap_req_failure(sm
, data
);
1137 len
= be_to_host16(hdr
->length
);
1138 if (len
> wpabuf_len(in_decrypted
)) {
1139 wpa_printf(MSG_INFO
, "EAP-PEAP: Length mismatch in "
1140 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1141 (unsigned long) wpabuf_len(in_decrypted
),
1142 (unsigned long) len
);
1143 wpabuf_free(in_decrypted
);
1144 eap_peap_req_failure(sm
, data
);
1147 wpa_printf(MSG_DEBUG
, "EAP-PEAP: received Phase 2: code=%d "
1148 "identifier=%d length=%lu", hdr
->code
, hdr
->identifier
,
1149 (unsigned long) len
);
1150 switch (hdr
->code
) {
1151 case EAP_CODE_RESPONSE
:
1152 eap_peap_process_phase2_response(sm
, data
, in_decrypted
);
1154 case EAP_CODE_SUCCESS
:
1155 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Success");
1156 if (data
->state
== SUCCESS_REQ
) {
1157 eap_peap_state(data
, SUCCESS
);
1160 case EAP_CODE_FAILURE
:
1161 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Phase 2 Failure");
1162 eap_peap_state(data
, FAILURE
);
1165 wpa_printf(MSG_INFO
, "EAP-PEAP: Unexpected code=%d in "
1166 "Phase 2 EAP header", hdr
->code
);
1170 wpabuf_free(in_decrypted
);
1174 static int eap_peapv2_start_phase2(struct eap_sm
*sm
,
1175 struct eap_peap_data
*data
)
1177 struct wpabuf
*buf
, *buf2
;
1179 wpa_printf(MSG_DEBUG
, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1180 "payload in the same message");
1181 eap_peap_state(data
, PHASE1_ID2
);
1182 if (eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
))
1185 /* TODO: which Id to use here? */
1186 buf
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, 6);
1190 buf2
= eap_peapv2_tlv_eap_payload(buf
);
1194 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Identity Request", buf2
);
1196 buf
= tls_connection_encrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1201 wpa_printf(MSG_INFO
, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1206 wpa_hexdump_buf(MSG_DEBUG
, "EAP-PEAPv2: Encrypted Identity Request",
1209 /* Append TLS data into the pending buffer after the Server Finished */
1210 if (wpabuf_resize(&data
->ssl
.tls_out
, wpabuf_len(buf
)) < 0) {
1214 wpabuf_put_buf(data
->ssl
.tls_out
, buf
);
1221 static int eap_peap_process_version(struct eap_sm
*sm
, void *priv
,
1224 struct eap_peap_data
*data
= priv
;
1226 data
->recv_version
= peer_version
;
1227 if (data
->force_version
>= 0 && peer_version
!= data
->force_version
) {
1228 wpa_printf(MSG_INFO
, "EAP-PEAP: peer did not select the forced"
1229 " version (forced=%d peer=%d) - reject",
1230 data
->force_version
, peer_version
);
1233 if (peer_version
< data
->peap_version
) {
1234 wpa_printf(MSG_DEBUG
, "EAP-PEAP: peer ver=%d, own ver=%d; "
1236 peer_version
, data
->peap_version
, peer_version
);
1237 data
->peap_version
= peer_version
;
1244 static void eap_peap_process_msg(struct eap_sm
*sm
, void *priv
,
1245 const struct wpabuf
*respData
)
1247 struct eap_peap_data
*data
= priv
;
1249 switch (data
->state
) {
1251 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0) {
1252 eap_peap_state(data
, FAILURE
);
1256 if (data
->peap_version
>= 2 &&
1257 tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1258 if (eap_peapv2_start_phase2(sm
, data
)) {
1259 eap_peap_state(data
, FAILURE
);
1265 eap_peap_state(data
, PHASE2_ID
);
1266 eap_peap_phase2_init(sm
, data
, EAP_TYPE_IDENTITY
);
1273 eap_peap_process_phase2(sm
, data
, respData
, data
->ssl
.tls_in
);
1276 eap_peap_state(data
, SUCCESS
);
1279 eap_peap_state(data
, FAILURE
);
1282 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Unexpected state %d in %s",
1283 data
->state
, __func__
);
1289 static void eap_peap_process(struct eap_sm
*sm
, void *priv
,
1290 struct wpabuf
*respData
)
1292 struct eap_peap_data
*data
= priv
;
1293 if (eap_server_tls_process(sm
, &data
->ssl
, respData
, data
,
1294 EAP_TYPE_PEAP
, eap_peap_process_version
,
1295 eap_peap_process_msg
) < 0)
1296 eap_peap_state(data
, FAILURE
);
1300 static Boolean
eap_peap_isDone(struct eap_sm
*sm
, void *priv
)
1302 struct eap_peap_data
*data
= priv
;
1303 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1307 static u8
* eap_peap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1309 struct eap_peap_data
*data
= priv
;
1312 if (data
->state
!= SUCCESS
)
1315 if (data
->crypto_binding_used
) {
1318 * Note: It looks like Microsoft implementation requires null
1319 * termination for this label while the one used for deriving
1320 * IPMK|CMK did not use null termination.
1322 peap_prfplus(data
->peap_version
, data
->ipmk
, 40,
1323 "Session Key Generating Function",
1324 (u8
*) "\00", 1, csk
, sizeof(csk
));
1325 wpa_hexdump_key(MSG_DEBUG
, "EAP-PEAP: CSK", csk
, sizeof(csk
));
1326 eapKeyData
= os_malloc(EAP_TLS_KEY_LEN
);
1328 os_memcpy(eapKeyData
, csk
, EAP_TLS_KEY_LEN
);
1329 *len
= EAP_TLS_KEY_LEN
;
1330 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1331 eapKeyData
, EAP_TLS_KEY_LEN
);
1333 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive "
1340 /* TODO: PEAPv1 - different label in some cases */
1341 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
1342 "client EAP encryption",
1345 *len
= EAP_TLS_KEY_LEN
;
1346 wpa_hexdump(MSG_DEBUG
, "EAP-PEAP: Derived key",
1347 eapKeyData
, EAP_TLS_KEY_LEN
);
1349 wpa_printf(MSG_DEBUG
, "EAP-PEAP: Failed to derive key");
1356 static Boolean
eap_peap_isSuccess(struct eap_sm
*sm
, void *priv
)
1358 struct eap_peap_data
*data
= priv
;
1359 return data
->state
== SUCCESS
;
1363 int eap_server_peap_register(void)
1365 struct eap_method
*eap
;
1368 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
1369 EAP_VENDOR_IETF
, EAP_TYPE_PEAP
, "PEAP");
1373 eap
->init
= eap_peap_init
;
1374 eap
->reset
= eap_peap_reset
;
1375 eap
->buildReq
= eap_peap_buildReq
;
1376 eap
->check
= eap_peap_check
;
1377 eap
->process
= eap_peap_process
;
1378 eap
->isDone
= eap_peap_isDone
;
1379 eap
->getKey
= eap_peap_getKey
;
1380 eap
->isSuccess
= eap_peap_isSuccess
;
1382 ret
= eap_server_method_register(eap
);
1384 eap_server_method_free(eap
);