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.
19 #include "eap_tls_common.h"
20 #include "eap_common/eap_tlv_common.h"
24 /* Maximum supported PEAP version
25 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
26 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
27 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
29 #define EAP_PEAP_VERSION 1
32 static void eap_peap_reset(struct eap_sm *sm, void *priv);
35 struct eap_peap_data {
36 struct eap_ssl_data ssl;
38 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
40 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
44 const struct eap_method *phase2_method;
47 struct wpabuf *pending_phase2_resp;
51 static const char * eap_peap_state_txt(int state)
61 return "PHASE2_START";
65 return "PHASE2_METHOD";
82 static void eap_peap_state(struct eap_peap_data *data, int state)
84 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
85 eap_peap_state_txt(data->state),
86 eap_peap_state_txt(state));
91 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
94 struct eap_tlv_hdr *tlv;
99 /* Encapsulate EAP packet in EAP-Payload TLV */
100 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
101 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
103 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
104 "for TLV encapsulation");
108 tlv = wpabuf_put(e, sizeof(*tlv));
109 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
110 EAP_TLV_EAP_PAYLOAD_TLV);
111 tlv->length = host_to_be16(wpabuf_len(buf));
112 wpabuf_put_buf(e, buf);
118 static EapType eap_peap_req_success(struct eap_sm *sm,
119 struct eap_peap_data *data)
121 if (data->state == FAILURE || data->state == FAILURE_REQ) {
122 eap_peap_state(data, FAILURE);
123 return EAP_TYPE_NONE;
126 if (data->peap_version == 0) {
127 sm->tlv_request = TLV_REQ_SUCCESS;
128 eap_peap_state(data, PHASE2_TLV);
131 eap_peap_state(data, SUCCESS_REQ);
132 return EAP_TYPE_NONE;
137 static EapType eap_peap_req_failure(struct eap_sm *sm,
138 struct eap_peap_data *data)
140 if (data->state == FAILURE || data->state == FAILURE_REQ ||
141 data->state == SUCCESS_REQ ||
142 (data->phase2_method &&
143 data->phase2_method->method == EAP_TYPE_TLV)) {
144 eap_peap_state(data, FAILURE);
145 return EAP_TYPE_NONE;
148 if (data->peap_version == 0) {
149 sm->tlv_request = TLV_REQ_FAILURE;
150 eap_peap_state(data, PHASE2_TLV);
153 eap_peap_state(data, FAILURE_REQ);
154 return EAP_TYPE_NONE;
159 static void * eap_peap_init(struct eap_sm *sm)
161 struct eap_peap_data *data;
163 data = os_zalloc(sizeof(*data));
166 data->peap_version = EAP_PEAP_VERSION;
167 data->force_version = -1;
168 if (sm->user && sm->user->force_version >= 0) {
169 data->force_version = sm->user->force_version;
170 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
171 data->force_version);
172 data->peap_version = data->force_version;
176 if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
177 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
178 eap_peap_reset(sm, data);
186 static void eap_peap_reset(struct eap_sm *sm, void *priv)
188 struct eap_peap_data *data = priv;
191 if (data->phase2_priv && data->phase2_method)
192 data->phase2_method->reset(sm, data->phase2_priv);
193 eap_server_tls_ssl_deinit(sm, &data->ssl);
194 wpabuf_free(data->pending_phase2_resp);
199 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
200 struct eap_peap_data *data, u8 id)
204 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
205 EAP_CODE_REQUEST, id);
207 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
209 eap_peap_state(data, FAILURE);
213 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
215 eap_peap_state(data, PHASE1);
221 static struct wpabuf * eap_peap_build_req(struct eap_sm *sm,
222 struct eap_peap_data *data, u8 id)
227 res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_PEAP,
228 data->peap_version, id, &req);
230 if (data->peap_version < 2 &&
231 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
232 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, starting "
234 eap_peap_state(data, PHASE2_START);
238 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
244 static struct wpabuf * eap_peap_encrypt(struct eap_sm *sm,
245 struct eap_peap_data *data,
246 u8 id, const u8 *plain,
252 /* TODO: add support for fragmentation, if needed. This will need to
253 * add TLS Message Length field, if the frame is fragmented. */
254 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP,
255 1 + data->ssl.tls_out_limit,
256 EAP_CODE_REQUEST, id);
260 wpabuf_put_u8(buf, data->peap_version);
262 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
263 plain, plain_len, wpabuf_put(buf, 0),
264 data->ssl.tls_out_limit);
266 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
272 wpabuf_put(buf, res);
279 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
280 struct eap_peap_data *data,
283 struct wpabuf *buf, *encr_req;
287 buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
288 if (data->peap_version >= 2 && buf)
289 buf = eap_peapv2_tlv_eap_payload(buf);
293 req = wpabuf_head(buf);
294 req_len = wpabuf_len(buf);
295 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
298 if (data->peap_version == 0 &&
299 data->phase2_method->method != EAP_TYPE_TLV) {
300 req += sizeof(struct eap_hdr);
301 req_len -= sizeof(struct eap_hdr);
304 encr_req = eap_peap_encrypt(sm, data, id, req, req_len);
311 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
312 struct eap_peap_data *data,
315 struct wpabuf *encr_req;
319 req_len = sizeof(*hdr);
320 hdr = os_zalloc(req_len);
324 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
325 hdr->identifier = id;
326 hdr->length = host_to_be16(req_len);
328 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
329 (u8 *) hdr, req_len);
331 encr_req = eap_peap_encrypt(sm, data, id, (u8 *) hdr, req_len);
338 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
340 struct eap_peap_data *data = priv;
342 switch (data->state) {
344 return eap_peap_build_start(sm, data, id);
347 return eap_peap_build_req(sm, data, id);
351 return eap_peap_build_phase2_req(sm, data, id);
353 return eap_peap_build_phase2_term(sm, data, id, 1);
355 return eap_peap_build_phase2_term(sm, data, id, 0);
357 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
358 __func__, data->state);
364 static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
365 struct wpabuf *respData)
370 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
371 if (pos == NULL || len < 1) {
372 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
380 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
383 if (data->phase2_priv && data->phase2_method) {
384 data->phase2_method->reset(sm, data->phase2_priv);
385 data->phase2_method = NULL;
386 data->phase2_priv = NULL;
388 data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
390 if (!data->phase2_method)
394 data->phase2_priv = data->phase2_method->init(sm);
400 static void eap_peap_process_phase2_response(struct eap_sm *sm,
401 struct eap_peap_data *data,
402 struct wpabuf *in_data)
404 u8 next_type = EAP_TYPE_NONE;
405 const struct eap_hdr *hdr;
409 if (data->phase2_priv == NULL) {
410 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
411 "initialized?!", __func__);
415 hdr = wpabuf_head(in_data);
416 pos = (const u8 *) (hdr + 1);
418 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
419 left = wpabuf_len(in_data) - sizeof(*hdr);
420 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
421 "allowed types", pos + 1, left - 1);
422 eap_sm_process_nak(sm, pos + 1, left - 1);
423 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
424 sm->user->methods[sm->user_eap_method_index].method !=
426 next_type = sm->user->methods[
427 sm->user_eap_method_index++].method;
428 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
431 next_type = eap_peap_req_failure(sm, data);
433 eap_peap_phase2_init(sm, data, next_type);
437 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
438 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
439 "ignore the packet");
443 data->phase2_method->process(sm, data->phase2_priv, in_data);
445 if (sm->method_pending == METHOD_PENDING_WAIT) {
446 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
447 "pending wait state - save decrypted response");
448 wpabuf_free(data->pending_phase2_resp);
449 data->pending_phase2_resp = wpabuf_dup(in_data);
452 if (!data->phase2_method->isDone(sm, data->phase2_priv))
455 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
456 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
457 next_type = eap_peap_req_failure(sm, data);
458 eap_peap_phase2_init(sm, data, next_type);
462 switch (data->state) {
465 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
466 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
467 "Identity not found in the user "
469 sm->identity, sm->identity_len);
470 next_type = eap_peap_req_failure(sm, data);
474 eap_peap_state(data, PHASE2_METHOD);
475 next_type = sm->user->methods[0].method;
476 sm->user_eap_method_index = 1;
477 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
480 next_type = eap_peap_req_success(sm, data);
483 if (sm->tlv_request == TLV_REQ_SUCCESS ||
484 data->state == SUCCESS_REQ) {
485 eap_peap_state(data, SUCCESS);
487 eap_peap_state(data, FAILURE);
493 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
494 __func__, data->state);
498 eap_peap_phase2_init(sm, data, next_type);
502 static void eap_peap_process_phase2(struct eap_sm *sm,
503 struct eap_peap_data *data,
504 const struct wpabuf *respData,
505 const u8 *in_data, size_t in_len)
507 struct wpabuf *in_decrypted;
508 int len_decrypted, res;
509 const struct eap_hdr *hdr;
512 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
513 " Phase 2", (unsigned long) in_len);
515 if (data->pending_phase2_resp) {
516 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
517 "skip decryption and use old data");
518 eap_peap_process_phase2_response(sm, data,
519 data->pending_phase2_resp);
520 wpabuf_free(data->pending_phase2_resp);
521 data->pending_phase2_resp = NULL;
525 /* FIX: get rid of const -> non-const typecast */
526 res = eap_server_tls_data_reassemble(sm, &data->ssl, (u8 **) &in_data,
528 if (res < 0 || res == 1)
532 if (data->ssl.tls_in_total > buf_len)
533 buf_len = data->ssl.tls_in_total;
534 in_decrypted = wpabuf_alloc(buf_len);
535 if (in_decrypted == NULL) {
536 os_free(data->ssl.tls_in);
537 data->ssl.tls_in = NULL;
538 data->ssl.tls_in_len = 0;
539 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
544 len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
546 wpabuf_mhead(in_decrypted),
548 os_free(data->ssl.tls_in);
549 data->ssl.tls_in = NULL;
550 data->ssl.tls_in_len = 0;
551 if (len_decrypted < 0) {
552 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
554 wpabuf_free(in_decrypted);
555 eap_peap_state(data, FAILURE);
558 wpabuf_put(in_decrypted, len_decrypted);
560 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
563 hdr = wpabuf_head(in_decrypted);
565 if (data->peap_version == 0 && data->state != PHASE2_TLV) {
566 const struct eap_hdr *resp;
567 struct eap_hdr *nhdr;
568 struct wpabuf *nbuf =
569 wpabuf_alloc(sizeof(struct eap_hdr) +
570 wpabuf_len(in_decrypted));
572 wpabuf_free(in_decrypted);
576 resp = wpabuf_head(respData);
577 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
578 nhdr->code = resp->code;
579 nhdr->identifier = resp->identifier;
580 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
581 wpabuf_len(in_decrypted));
582 wpabuf_put_buf(nbuf, in_decrypted);
583 wpabuf_free(in_decrypted);
586 } else if (data->peap_version >= 2) {
587 struct eap_tlv_hdr *tlv;
590 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
591 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
593 wpabuf_free(in_decrypted);
596 tlv = wpabuf_mhead(in_decrypted);
597 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
598 EAP_TLV_EAP_PAYLOAD_TLV) {
599 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
600 wpabuf_free(in_decrypted);
603 if (sizeof(*tlv) + be_to_host16(tlv->length) >
604 wpabuf_len(in_decrypted)) {
605 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
607 wpabuf_free(in_decrypted);
610 hdr = (struct eap_hdr *) (tlv + 1);
611 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
612 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
613 "EAP packet in EAP TLV");
614 wpabuf_free(in_decrypted);
618 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
620 wpabuf_free(in_decrypted);
624 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
625 wpabuf_free(in_decrypted);
629 hdr = wpabuf_head(in_decrypted);
630 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
631 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
632 "EAP frame (len=%lu)",
633 (unsigned long) wpabuf_len(in_decrypted));
634 wpabuf_free(in_decrypted);
635 eap_peap_req_failure(sm, data);
638 len = be_to_host16(hdr->length);
639 if (len > wpabuf_len(in_decrypted)) {
640 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
641 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
642 (unsigned long) wpabuf_len(in_decrypted),
643 (unsigned long) len);
644 wpabuf_free(in_decrypted);
645 eap_peap_req_failure(sm, data);
648 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
649 "identifier=%d length=%lu", hdr->code, hdr->identifier,
650 (unsigned long) len);
652 case EAP_CODE_RESPONSE:
653 eap_peap_process_phase2_response(sm, data, in_decrypted);
655 case EAP_CODE_SUCCESS:
656 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
657 if (data->state == SUCCESS_REQ) {
658 eap_peap_state(data, SUCCESS);
661 case EAP_CODE_FAILURE:
662 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
663 eap_peap_state(data, FAILURE);
666 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
667 "Phase 2 EAP header", hdr->code);
671 os_free(in_decrypted);
675 static int eap_peapv2_start_phase2(struct eap_sm *sm,
676 struct eap_peap_data *data)
678 struct wpabuf *buf, *buf2;
682 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
683 "payload in the same message");
684 eap_peap_state(data, PHASE1_ID2);
685 if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
688 /* TODO: which Id to use here? */
689 buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
693 buf2 = eap_peapv2_tlv_eap_payload(buf);
697 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
699 buf = wpabuf_alloc(data->ssl.tls_out_limit);
705 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
706 wpabuf_head(buf2), wpabuf_len(buf2),
708 data->ssl.tls_out_limit);
712 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
718 wpabuf_put(buf, res);
719 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
722 /* Append TLS data into the pending buffer after the Server Finished */
723 tls_out = os_realloc(data->ssl.tls_out,
724 data->ssl.tls_out_len + wpabuf_len(buf));
725 if (tls_out == NULL) {
730 os_memcpy(tls_out + data->ssl.tls_out_len, wpabuf_head(buf),
732 data->ssl.tls_out = tls_out;
733 data->ssl.tls_out_len += wpabuf_len(buf);
741 static void eap_peap_process(struct eap_sm *sm, void *priv,
742 struct wpabuf *respData)
744 struct eap_peap_data *data = priv;
748 unsigned int tls_msg_len;
751 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
753 if (pos == NULL || left < 1)
757 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
758 "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
760 peer_version = flags & EAP_PEAP_VERSION_MASK;
761 if (data->force_version >= 0 && peer_version != data->force_version) {
762 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
763 " version (forced=%d peer=%d) - reject",
764 data->force_version, peer_version);
765 eap_peap_state(data, FAILURE);
768 if (peer_version < data->peap_version) {
769 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
771 peer_version, data->peap_version, peer_version);
772 data->peap_version = peer_version;
774 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
776 wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS "
778 eap_peap_state(data, FAILURE);
781 tls_msg_len = WPA_GET_BE32(pos);
782 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d",
784 if (data->ssl.tls_in_left == 0) {
785 data->ssl.tls_in_total = tls_msg_len;
786 data->ssl.tls_in_left = tls_msg_len;
787 os_free(data->ssl.tls_in);
788 data->ssl.tls_in = NULL;
789 data->ssl.tls_in_len = 0;
795 switch (data->state) {
797 if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
799 wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing "
801 eap_peap_state(data, FAILURE);
805 if (data->peap_version >= 2 &&
806 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
807 if (eap_peapv2_start_phase2(sm, data)) {
808 eap_peap_state(data, FAILURE);
814 eap_peap_state(data, PHASE2_ID);
815 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
821 eap_peap_process_phase2(sm, data, respData, pos, left);
824 eap_peap_state(data, SUCCESS);
827 eap_peap_state(data, FAILURE);
830 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
831 data->state, __func__);
835 if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
836 wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
837 "in TLS processing");
838 eap_peap_state(data, FAILURE);
843 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
845 struct eap_peap_data *data = priv;
846 return data->state == SUCCESS || data->state == FAILURE;
850 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
852 struct eap_peap_data *data = priv;
855 if (data->state != SUCCESS)
858 /* TODO: PEAPv1 - different label in some cases */
859 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
860 "client EAP encryption",
863 *len = EAP_TLS_KEY_LEN;
864 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
865 eapKeyData, EAP_TLS_KEY_LEN);
867 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
874 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
876 struct eap_peap_data *data = priv;
877 return data->state == SUCCESS;
881 int eap_server_peap_register(void)
883 struct eap_method *eap;
886 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
887 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
891 eap->init = eap_peap_init;
892 eap->reset = eap_peap_reset;
893 eap->buildReq = eap_peap_buildReq;
894 eap->check = eap_peap_check;
895 eap->process = eap_peap_process;
896 eap->isDone = eap_peap_isDone;
897 eap->getKey = eap_peap_getKey;
898 eap->isSuccess = eap_peap_isSuccess;
900 ret = eap_server_method_register(eap);
902 eap_server_method_free(eap);