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);