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"
26 /* Maximum supported PEAP version
27 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
28 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
29 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
31 #define EAP_PEAP_VERSION 1
34 static void eap_peap_reset(struct eap_sm *sm, void *priv);
37 struct eap_peap_data {
38 struct eap_ssl_data ssl;
40 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
41 PHASE2_METHOD, PHASE2_SOH,
42 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
47 const struct eap_method *phase2_method;
50 struct wpabuf *pending_phase2_resp;
51 enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
52 int crypto_binding_sent;
53 int crypto_binding_used;
54 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
59 size_t phase2_key_len;
60 struct wpabuf *soh_response;
64 static const char * eap_peap_state_txt(int state)
74 return "PHASE2_START";
78 return "PHASE2_METHOD";
97 static void eap_peap_state(struct eap_peap_data *data, int state)
99 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
100 eap_peap_state_txt(data->state),
101 eap_peap_state_txt(state));
106 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
109 struct eap_tlv_hdr *tlv;
114 /* Encapsulate EAP packet in EAP-Payload TLV */
115 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
116 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
118 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
119 "for TLV encapsulation");
123 tlv = wpabuf_put(e, sizeof(*tlv));
124 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
125 EAP_TLV_EAP_PAYLOAD_TLV);
126 tlv->length = host_to_be16(wpabuf_len(buf));
127 wpabuf_put_buf(e, buf);
133 static void eap_peap_req_success(struct eap_sm *sm,
134 struct eap_peap_data *data)
136 if (data->state == FAILURE || data->state == FAILURE_REQ) {
137 eap_peap_state(data, FAILURE);
141 if (data->peap_version == 0) {
142 data->tlv_request = TLV_REQ_SUCCESS;
143 eap_peap_state(data, PHASE2_TLV);
145 eap_peap_state(data, SUCCESS_REQ);
150 static void eap_peap_req_failure(struct eap_sm *sm,
151 struct eap_peap_data *data)
153 if (data->state == FAILURE || data->state == FAILURE_REQ ||
154 data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) {
155 eap_peap_state(data, FAILURE);
159 if (data->peap_version == 0) {
160 data->tlv_request = TLV_REQ_FAILURE;
161 eap_peap_state(data, PHASE2_TLV);
163 eap_peap_state(data, FAILURE_REQ);
168 static void * eap_peap_init(struct eap_sm *sm)
170 struct eap_peap_data *data;
172 data = os_zalloc(sizeof(*data));
175 data->peap_version = EAP_PEAP_VERSION;
176 data->force_version = -1;
177 if (sm->user && sm->user->force_version >= 0) {
178 data->force_version = sm->user->force_version;
179 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
180 data->force_version);
181 data->peap_version = data->force_version;
184 data->crypto_binding = OPTIONAL_BINDING;
186 if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
187 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
188 eap_peap_reset(sm, data);
196 static void eap_peap_reset(struct eap_sm *sm, void *priv)
198 struct eap_peap_data *data = priv;
201 if (data->phase2_priv && data->phase2_method)
202 data->phase2_method->reset(sm, data->phase2_priv);
203 eap_server_tls_ssl_deinit(sm, &data->ssl);
204 wpabuf_free(data->pending_phase2_resp);
205 os_free(data->phase2_key);
206 wpabuf_free(data->soh_response);
211 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
212 struct eap_peap_data *data, u8 id)
216 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
217 EAP_CODE_REQUEST, id);
219 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
221 eap_peap_state(data, FAILURE);
225 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
227 eap_peap_state(data, PHASE1);
233 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
234 struct eap_peap_data *data,
237 struct wpabuf *buf, *encr_req;
241 if (data->phase2_method == NULL || data->phase2_priv == NULL) {
242 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready");
245 buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
246 if (data->peap_version >= 2 && buf)
247 buf = eap_peapv2_tlv_eap_payload(buf);
251 req = wpabuf_head(buf);
252 req_len = wpabuf_len(buf);
253 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
256 if (data->peap_version == 0 &&
257 data->phase2_method->method != EAP_TYPE_TLV) {
258 req += sizeof(struct eap_hdr);
259 req_len -= sizeof(struct eap_hdr);
262 encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
270 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
271 struct eap_peap_data *data,
274 struct wpabuf *buf1, *buf, *encr_req;
278 buf1 = tncs_build_soh_request();
282 buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
283 EAP_CODE_REQUEST, id);
288 wpabuf_put_buf(buf, buf1);
291 req = wpabuf_head(buf);
292 req_len = wpabuf_len(buf);
294 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
297 req += sizeof(struct eap_hdr);
298 req_len -= sizeof(struct eap_hdr);
300 encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
308 static void eap_peap_get_isk(struct eap_peap_data *data,
309 u8 *isk, size_t isk_len)
313 os_memset(isk, 0, isk_len);
314 if (data->phase2_key == NULL)
317 key_len = data->phase2_key_len;
318 if (key_len > isk_len)
320 os_memcpy(isk, data->phase2_key, key_len);
324 void peap_prfplus(int version, const u8 *key, size_t key_len,
325 const char *label, const u8 *seed, size_t seed_len,
326 u8 *buf, size_t buf_len)
328 unsigned char counter = 0;
330 u8 hash[SHA1_MAC_LEN];
331 size_t label_len = os_strlen(label);
333 const unsigned char *addr[5];
338 addr[1] = (unsigned char *) label;
345 * PRF+(K, S, LEN) = T1 | T2 | ... | Tn
346 * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00)
347 * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00)
349 * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00)
361 * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where:
362 * T1 = HMAC-SHA1(K, S | LEN | 0x01)
363 * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02)
364 * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03)
365 * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04)
369 extra[0] = buf_len & 0xff;
378 while (pos < buf_len) {
380 plen = buf_len - pos;
381 hmac_sha1_vector(key, key_len, 5, addr, len, hash);
382 if (plen >= SHA1_MAC_LEN) {
383 os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
386 os_memcpy(&buf[pos], hash, plen);
389 len[0] = SHA1_MAC_LEN;
394 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
397 u8 isk[32], imck[60];
400 * Tunnel key (TK) is the first 60 octets of the key generated by
401 * phase 1 of PEAP (based on TLS).
403 tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
407 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
409 eap_peap_get_isk(data, isk, sizeof(isk));
410 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
413 * IPMK Seed = "Inner Methods Compound Keys" | ISK
414 * TempKey = First 40 octets of TK
415 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
416 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
417 * in the end of the label just before ISK; is that just a typo?)
419 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
420 peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
421 isk, sizeof(isk), imck, sizeof(imck));
422 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
427 /* TODO: fast-connect: IPMK|CMK = TK */
428 os_memcpy(data->ipmk, imck, 40);
429 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
430 os_memcpy(data->cmk, imck + 40, 20);
431 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
437 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
438 struct eap_peap_data *data,
441 struct wpabuf *buf, *encr_req;
444 len = 6; /* Result TLV */
445 if (data->crypto_binding != NO_BINDING)
446 len += 60; /* Cryptobinding TLV */
448 if (data->soh_response)
449 len += wpabuf_len(data->soh_response);
452 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
453 EAP_CODE_REQUEST, id);
457 wpabuf_put_u8(buf, 0x80); /* Mandatory */
458 wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
460 wpabuf_put_be16(buf, 2);
462 wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
463 EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
465 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
466 data->crypto_binding != NO_BINDING) {
468 u8 eap_type = EAP_TYPE_PEAP;
474 if (data->soh_response) {
475 wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
477 wpabuf_put_buf(buf, data->soh_response);
478 wpabuf_free(data->soh_response);
479 data->soh_response = NULL;
483 if (eap_peap_derive_cmk(sm, data) < 0 ||
484 os_get_random(data->binding_nonce, 32)) {
489 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
490 addr[0] = wpabuf_put(buf, 0);
495 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
496 if (data->peap_version >= 2)
497 tlv_type |= EAP_TLV_TYPE_MANDATORY;
498 wpabuf_put_be16(buf, tlv_type);
499 wpabuf_put_be16(buf, 56);
501 wpabuf_put_u8(buf, 0); /* Reserved */
502 wpabuf_put_u8(buf, data->peap_version); /* Version */
503 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
504 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
505 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
506 mac = wpabuf_put(buf, 20); /* Compound_MAC */
507 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
509 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
511 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
513 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
514 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
516 data->crypto_binding_sent = 1;
519 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
522 encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
530 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
531 struct eap_peap_data *data,
534 struct wpabuf *encr_req;
538 req_len = sizeof(*hdr);
539 hdr = os_zalloc(req_len);
543 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
544 hdr->identifier = id;
545 hdr->length = host_to_be16(req_len);
547 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
548 (u8 *) hdr, req_len);
550 encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
557 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
559 struct eap_peap_data *data = priv;
561 if (data->ssl.state == FRAG_ACK) {
562 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
566 if (data->ssl.state == WAIT_FRAG_ACK) {
567 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
568 data->peap_version, id);
571 switch (data->state) {
573 return eap_peap_build_start(sm, data, id);
576 if (data->peap_version < 2 &&
577 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
578 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
580 eap_peap_state(data, PHASE2_START);
585 wpabuf_free(data->ssl.out_buf);
586 data->ssl.out_used = 0;
587 data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id);
591 wpabuf_free(data->ssl.out_buf);
592 data->ssl.out_used = 0;
593 data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id);
597 wpabuf_free(data->ssl.out_buf);
598 data->ssl.out_used = 0;
599 data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id);
602 wpabuf_free(data->ssl.out_buf);
603 data->ssl.out_used = 0;
604 data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
608 wpabuf_free(data->ssl.out_buf);
609 data->ssl.out_used = 0;
610 data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
614 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
615 __func__, data->state);
619 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
620 data->peap_version, id);
624 static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
625 struct wpabuf *respData)
630 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
631 if (pos == NULL || len < 1) {
632 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
640 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
643 if (data->phase2_priv && data->phase2_method) {
644 data->phase2_method->reset(sm, data->phase2_priv);
645 data->phase2_method = NULL;
646 data->phase2_priv = NULL;
648 data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
650 if (!data->phase2_method)
654 data->phase2_priv = data->phase2_method->init(sm);
660 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
661 struct eap_peap_data *data,
662 const u8 *crypto_tlv,
663 size_t crypto_tlv_len)
665 u8 buf[61], mac[SHA1_MAC_LEN];
668 if (crypto_tlv_len != 4 + 56) {
669 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
670 "length %d", (int) crypto_tlv_len);
675 pos += 4; /* TLV header */
676 if (pos[1] != data->peap_version) {
677 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
678 "mismatch (was %d; expected %d)",
679 pos[1], data->peap_version);
684 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
685 "SubType %d", pos[3]);
689 pos += 32; /* Nonce */
691 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
692 os_memcpy(buf, crypto_tlv, 60);
693 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
694 buf[60] = EAP_TYPE_PEAP;
695 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
697 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
698 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
699 "cryptobinding TLV");
700 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
701 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
706 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
712 static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
713 struct eap_peap_data *data,
714 struct wpabuf *in_data)
718 const u8 *result_tlv = NULL, *crypto_tlv = NULL;
719 size_t result_tlv_len = 0, crypto_tlv_len = 0;
720 int tlv_type, mandatory, tlv_len;
722 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
724 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
729 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
731 mandatory = !!(pos[0] & 0x80);
732 tlv_type = pos[0] & 0x3f;
733 tlv_type = (tlv_type << 8) | pos[1];
734 tlv_len = ((int) pos[2] << 8) | pos[3];
737 if ((size_t) tlv_len > left) {
738 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
739 "(tlv_len=%d left=%lu)", tlv_len,
740 (unsigned long) left);
741 eap_peap_state(data, FAILURE);
745 case EAP_TLV_RESULT_TLV:
747 result_tlv_len = tlv_len;
749 case EAP_TLV_CRYPTO_BINDING_TLV:
751 crypto_tlv_len = tlv_len;
754 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
756 mandatory ? " (mandatory)" : "");
758 eap_peap_state(data, FAILURE);
761 /* Ignore this TLV, but process other TLVs */
769 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
770 "Request (left=%lu)", (unsigned long) left);
771 eap_peap_state(data, FAILURE);
775 /* Process supported TLVs */
776 if (crypto_tlv && data->crypto_binding_sent) {
777 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
778 crypto_tlv, crypto_tlv_len);
779 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
780 crypto_tlv_len + 4) < 0) {
781 eap_peap_state(data, FAILURE);
784 data->crypto_binding_used = 1;
785 } else if (!crypto_tlv && data->crypto_binding_sent &&
786 data->crypto_binding == REQUIRE_BINDING) {
787 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
788 eap_peap_state(data, FAILURE);
794 const char *requested;
796 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
797 result_tlv, result_tlv_len);
798 if (result_tlv_len < 2) {
799 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
801 (unsigned long) result_tlv_len);
802 eap_peap_state(data, FAILURE);
805 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
807 status = WPA_GET_BE16(result_tlv);
808 if (status == EAP_TLV_RESULT_SUCCESS) {
809 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
810 "- requested %s", requested);
811 if (data->tlv_request == TLV_REQ_SUCCESS)
812 eap_peap_state(data, SUCCESS);
814 eap_peap_state(data, FAILURE);
816 } else if (status == EAP_TLV_RESULT_FAILURE) {
817 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
818 "- requested %s", requested);
819 eap_peap_state(data, FAILURE);
821 wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
822 "Status %d", status);
823 eap_peap_state(data, FAILURE);
830 static void eap_peap_process_phase2_soh(struct eap_sm *sm,
831 struct eap_peap_data *data,
832 struct wpabuf *in_data)
834 const u8 *pos, *vpos;
836 const u8 *soh_tlv = NULL;
837 size_t soh_tlv_len = 0;
838 int tlv_type, mandatory, tlv_len, vtlv_len;
842 pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
844 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
845 "Extensions Method header - skip TNC");
850 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
852 mandatory = !!(pos[0] & 0x80);
853 tlv_type = pos[0] & 0x3f;
854 tlv_type = (tlv_type << 8) | pos[1];
855 tlv_len = ((int) pos[2] << 8) | pos[3];
858 if ((size_t) tlv_len > left) {
859 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
860 "(tlv_len=%d left=%lu)", tlv_len,
861 (unsigned long) left);
862 eap_peap_state(data, FAILURE);
866 case EAP_TLV_VENDOR_SPECIFIC_TLV:
868 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
869 "vendor specific TLV (len=%d)",
871 eap_peap_state(data, FAILURE);
875 vendor_id = WPA_GET_BE32(pos);
876 if (vendor_id != EAP_VENDOR_MICROSOFT) {
878 eap_peap_state(data, FAILURE);
885 mandatory = !!(vpos[0] & 0x80);
886 tlv_type = vpos[0] & 0x3f;
887 tlv_type = (tlv_type << 8) | vpos[1];
888 vtlv_len = ((int) vpos[2] << 8) | vpos[3];
890 if (vpos + vtlv_len > pos + left) {
891 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
893 eap_peap_state(data, FAILURE);
899 soh_tlv_len = vtlv_len;
903 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
904 "Type %d%s", tlv_type,
905 mandatory ? " (mandatory)" : "");
907 eap_peap_state(data, FAILURE);
910 /* Ignore this TLV, but process other TLVs */
913 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
915 mandatory ? " (mandatory)" : "");
917 eap_peap_state(data, FAILURE);
920 /* Ignore this TLV, but process other TLVs */
928 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
929 "Request (left=%lu)", (unsigned long) left);
930 eap_peap_state(data, FAILURE);
934 /* Process supported TLVs */
937 wpabuf_free(data->soh_response);
938 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
941 eap_peap_state(data, FAILURE);
945 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
946 eap_peap_state(data, FAILURE);
951 eap_peap_state(data, PHASE2_METHOD);
952 next_type = sm->user->methods[0].method;
953 sm->user_eap_method_index = 1;
954 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
955 eap_peap_phase2_init(sm, data, next_type);
960 static void eap_peap_process_phase2_response(struct eap_sm *sm,
961 struct eap_peap_data *data,
962 struct wpabuf *in_data)
964 u8 next_type = EAP_TYPE_NONE;
965 const struct eap_hdr *hdr;
969 if (data->state == PHASE2_TLV) {
970 eap_peap_process_phase2_tlv(sm, data, in_data);
975 if (data->state == PHASE2_SOH) {
976 eap_peap_process_phase2_soh(sm, data, in_data);
981 if (data->phase2_priv == NULL) {
982 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
983 "initialized?!", __func__);
987 hdr = wpabuf_head(in_data);
988 pos = (const u8 *) (hdr + 1);
990 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
991 left = wpabuf_len(in_data) - sizeof(*hdr);
992 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
993 "allowed types", pos + 1, left - 1);
994 eap_sm_process_nak(sm, pos + 1, left - 1);
995 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
996 sm->user->methods[sm->user_eap_method_index].method !=
998 next_type = sm->user->methods[
999 sm->user_eap_method_index++].method;
1000 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
1003 eap_peap_req_failure(sm, data);
1004 next_type = EAP_TYPE_NONE;
1006 eap_peap_phase2_init(sm, data, next_type);
1010 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
1011 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
1012 "ignore the packet");
1016 data->phase2_method->process(sm, data->phase2_priv, in_data);
1018 if (sm->method_pending == METHOD_PENDING_WAIT) {
1019 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
1020 "pending wait state - save decrypted response");
1021 wpabuf_free(data->pending_phase2_resp);
1022 data->pending_phase2_resp = wpabuf_dup(in_data);
1025 if (!data->phase2_method->isDone(sm, data->phase2_priv))
1028 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
1029 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
1030 eap_peap_req_failure(sm, data);
1031 next_type = EAP_TYPE_NONE;
1032 eap_peap_phase2_init(sm, data, next_type);
1036 os_free(data->phase2_key);
1037 if (data->phase2_method->getKey) {
1038 data->phase2_key = data->phase2_method->getKey(
1039 sm, data->phase2_priv, &data->phase2_key_len);
1040 if (data->phase2_key == NULL) {
1041 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
1043 eap_peap_req_failure(sm, data);
1044 eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
1048 if (data->phase2_key_len == 32 &&
1049 data->phase2_method->vendor == EAP_VENDOR_IETF &&
1050 data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
1052 * Microsoft uses reverse order for MS-MPPE keys in
1053 * EAP-PEAP when compared to EAP-FAST derivation of
1054 * ISK. Swap the keys here to get the correct ISK for
1055 * EAP-PEAPv0 cryptobinding.
1058 os_memcpy(tmp, data->phase2_key, 16);
1059 os_memcpy(data->phase2_key, data->phase2_key + 16, 16);
1060 os_memcpy(data->phase2_key + 16, tmp, 16);
1064 switch (data->state) {
1068 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1069 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
1070 "Identity not found in the user "
1072 sm->identity, sm->identity_len);
1073 eap_peap_req_failure(sm, data);
1074 next_type = EAP_TYPE_NONE;
1079 if (data->state != PHASE2_SOH && sm->tnc &&
1080 data->peap_version == 0) {
1081 eap_peap_state(data, PHASE2_SOH);
1082 wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
1084 next_type = EAP_TYPE_NONE;
1087 #endif /* EAP_TNC */
1089 eap_peap_state(data, PHASE2_METHOD);
1090 next_type = sm->user->methods[0].method;
1091 sm->user_eap_method_index = 1;
1092 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
1095 eap_peap_req_success(sm, data);
1096 next_type = EAP_TYPE_NONE;
1101 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
1102 __func__, data->state);
1106 eap_peap_phase2_init(sm, data, next_type);
1110 static void eap_peap_process_phase2(struct eap_sm *sm,
1111 struct eap_peap_data *data,
1112 const struct wpabuf *respData,
1113 struct wpabuf *in_buf)
1115 struct wpabuf *in_decrypted;
1117 const struct eap_hdr *hdr;
1118 size_t buf_len, len;
1122 in_data = wpabuf_mhead(in_buf);
1123 in_len = wpabuf_len(in_buf);
1125 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1126 " Phase 2", (unsigned long) in_len);
1128 if (data->pending_phase2_resp) {
1129 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1130 "skip decryption and use old data");
1131 eap_peap_process_phase2_response(sm, data,
1132 data->pending_phase2_resp);
1133 wpabuf_free(data->pending_phase2_resp);
1134 data->pending_phase2_resp = NULL;
1140 * Even though we try to disable TLS compression, it is possible that
1141 * this cannot be done with all TLS libraries. Add extra buffer space
1142 * to handle the possibility of the decrypted data being longer than
1147 in_decrypted = wpabuf_alloc(buf_len);
1148 if (in_decrypted == NULL) {
1149 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
1154 len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1156 wpabuf_mhead(in_decrypted),
1158 if (len_decrypted < 0) {
1159 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1161 wpabuf_free(in_decrypted);
1162 eap_peap_state(data, FAILURE);
1165 wpabuf_put(in_decrypted, len_decrypted);
1167 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1170 hdr = wpabuf_head(in_decrypted);
1172 if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1173 const struct eap_hdr *resp;
1174 struct eap_hdr *nhdr;
1175 struct wpabuf *nbuf =
1176 wpabuf_alloc(sizeof(struct eap_hdr) +
1177 wpabuf_len(in_decrypted));
1179 wpabuf_free(in_decrypted);
1183 resp = wpabuf_head(respData);
1184 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1185 nhdr->code = resp->code;
1186 nhdr->identifier = resp->identifier;
1187 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1188 wpabuf_len(in_decrypted));
1189 wpabuf_put_buf(nbuf, in_decrypted);
1190 wpabuf_free(in_decrypted);
1192 in_decrypted = nbuf;
1193 } else if (data->peap_version >= 2) {
1194 struct eap_tlv_hdr *tlv;
1195 struct wpabuf *nmsg;
1197 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
1198 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
1200 wpabuf_free(in_decrypted);
1203 tlv = wpabuf_mhead(in_decrypted);
1204 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
1205 EAP_TLV_EAP_PAYLOAD_TLV) {
1206 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
1207 wpabuf_free(in_decrypted);
1210 if (sizeof(*tlv) + be_to_host16(tlv->length) >
1211 wpabuf_len(in_decrypted)) {
1212 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
1214 wpabuf_free(in_decrypted);
1217 hdr = (struct eap_hdr *) (tlv + 1);
1218 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
1219 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
1220 "EAP packet in EAP TLV");
1221 wpabuf_free(in_decrypted);
1225 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
1227 wpabuf_free(in_decrypted);
1231 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
1232 wpabuf_free(in_decrypted);
1233 in_decrypted = nmsg;
1236 hdr = wpabuf_head(in_decrypted);
1237 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1238 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1239 "EAP frame (len=%lu)",
1240 (unsigned long) wpabuf_len(in_decrypted));
1241 wpabuf_free(in_decrypted);
1242 eap_peap_req_failure(sm, data);
1245 len = be_to_host16(hdr->length);
1246 if (len > wpabuf_len(in_decrypted)) {
1247 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1248 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1249 (unsigned long) wpabuf_len(in_decrypted),
1250 (unsigned long) len);
1251 wpabuf_free(in_decrypted);
1252 eap_peap_req_failure(sm, data);
1255 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1256 "identifier=%d length=%lu", hdr->code, hdr->identifier,
1257 (unsigned long) len);
1258 switch (hdr->code) {
1259 case EAP_CODE_RESPONSE:
1260 eap_peap_process_phase2_response(sm, data, in_decrypted);
1262 case EAP_CODE_SUCCESS:
1263 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1264 if (data->state == SUCCESS_REQ) {
1265 eap_peap_state(data, SUCCESS);
1268 case EAP_CODE_FAILURE:
1269 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1270 eap_peap_state(data, FAILURE);
1273 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1274 "Phase 2 EAP header", hdr->code);
1278 os_free(in_decrypted);
1282 static int eap_peapv2_start_phase2(struct eap_sm *sm,
1283 struct eap_peap_data *data)
1285 struct wpabuf *buf, *buf2;
1288 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1289 "payload in the same message");
1290 eap_peap_state(data, PHASE1_ID2);
1291 if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
1294 /* TODO: which Id to use here? */
1295 buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
1299 buf2 = eap_peapv2_tlv_eap_payload(buf);
1303 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
1305 buf = wpabuf_alloc(data->ssl.tls_out_limit);
1311 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
1312 wpabuf_head(buf2), wpabuf_len(buf2),
1314 data->ssl.tls_out_limit);
1318 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1324 wpabuf_put(buf, res);
1325 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
1328 /* Append TLS data into the pending buffer after the Server Finished */
1329 if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
1333 wpabuf_put_buf(data->ssl.out_buf, buf);
1340 static int eap_peap_process_version(struct eap_sm *sm, void *priv,
1343 struct eap_peap_data *data = priv;
1345 data->recv_version = peer_version;
1346 if (data->force_version >= 0 && peer_version != data->force_version) {
1347 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1348 " version (forced=%d peer=%d) - reject",
1349 data->force_version, peer_version);
1352 if (peer_version < data->peap_version) {
1353 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1355 peer_version, data->peap_version, peer_version);
1356 data->peap_version = peer_version;
1363 static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
1364 const struct wpabuf *respData)
1366 struct eap_peap_data *data = priv;
1368 switch (data->state) {
1370 if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1371 eap_peap_state(data, FAILURE);
1375 if (data->peap_version >= 2 &&
1376 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1377 if (eap_peapv2_start_phase2(sm, data)) {
1378 eap_peap_state(data, FAILURE);
1384 eap_peap_state(data, PHASE2_ID);
1385 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
1392 eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);
1395 eap_peap_state(data, SUCCESS);
1398 eap_peap_state(data, FAILURE);
1401 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1402 data->state, __func__);
1408 static void eap_peap_process(struct eap_sm *sm, void *priv,
1409 struct wpabuf *respData)
1411 struct eap_peap_data *data = priv;
1412 if (eap_server_tls_process(sm, &data->ssl, respData, data,
1413 EAP_TYPE_PEAP, eap_peap_process_version,
1414 eap_peap_process_msg) < 0)
1415 eap_peap_state(data, FAILURE);
1419 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
1421 struct eap_peap_data *data = priv;
1422 return data->state == SUCCESS || data->state == FAILURE;
1426 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1428 struct eap_peap_data *data = priv;
1431 if (data->state != SUCCESS)
1434 if (data->crypto_binding_used) {
1437 * Note: It looks like Microsoft implementation requires null
1438 * termination for this label while the one used for deriving
1439 * IPMK|CMK did not use null termination.
1441 peap_prfplus(data->peap_version, data->ipmk, 40,
1442 "Session Key Generating Function",
1443 (u8 *) "\00", 1, csk, sizeof(csk));
1444 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1445 eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1447 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1448 *len = EAP_TLS_KEY_LEN;
1449 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1450 eapKeyData, EAP_TLS_KEY_LEN);
1452 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1459 /* TODO: PEAPv1 - different label in some cases */
1460 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1461 "client EAP encryption",
1464 *len = EAP_TLS_KEY_LEN;
1465 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1466 eapKeyData, EAP_TLS_KEY_LEN);
1468 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1475 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1477 struct eap_peap_data *data = priv;
1478 return data->state == SUCCESS;
1482 int eap_server_peap_register(void)
1484 struct eap_method *eap;
1487 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1488 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1492 eap->init = eap_peap_init;
1493 eap->reset = eap_peap_reset;
1494 eap->buildReq = eap_peap_buildReq;
1495 eap->check = eap_peap_check;
1496 eap->process = eap_peap_process;
1497 eap->isDone = eap_peap_isDone;
1498 eap->getKey = eap_peap_getKey;
1499 eap->isSuccess = eap_peap_isSuccess;
1501 ret = eap_server_method_register(eap);
1503 eap_server_method_free(eap);