Import moonshot-gss-eap_0.9.2.orig.tar.gz
[mech_eap.git] / libeap / src / eap_server / eap_server_ttls.c
diff --git a/libeap/src/eap_server/eap_server_ttls.c b/libeap/src/eap_server/eap_server_ttls.c
deleted file mode 100644 (file)
index 702c50c..0000000
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*
- * hostapd / EAP-TTLS (RFC 5281)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "crypto/ms_funcs.h"
-#include "crypto/sha1.h"
-#include "crypto/tls.h"
-#include "eap_server/eap_i.h"
-#include "eap_server/eap_tls_common.h"
-#include "eap_common/chap.h"
-#include "eap_common/eap_ttls.h"
-
-
-/* Maximum supported TTLS version
- * 0 = RFC 5281
- * 1 = draft-funk-eap-ttls-v1-00.txt
- */
-#ifndef EAP_TTLS_VERSION
-#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
-#endif /* EAP_TTLS_VERSION */
-
-
-#define MSCHAPV2_KEY_LEN 16
-
-
-static void eap_ttls_reset(struct eap_sm *sm, void *priv);
-
-
-struct eap_ttls_data {
-       struct eap_ssl_data ssl;
-       enum {
-               START, PHASE1, PHASE2_START, PHASE2_METHOD,
-               PHASE2_MSCHAPV2_RESP, PHASE_FINISHED, SUCCESS, FAILURE
-       } state;
-
-       int ttls_version;
-       int force_version;
-       const struct eap_method *phase2_method;
-       void *phase2_priv;
-       int mschapv2_resp_ok;
-       u8 mschapv2_auth_response[20];
-       u8 mschapv2_ident;
-       int tls_ia_configured;
-       struct wpabuf *pending_phase2_eap_resp;
-       int tnc_started;
-};
-
-
-static const char * eap_ttls_state_txt(int state)
-{
-       switch (state) {
-       case START:
-               return "START";
-       case PHASE1:
-               return "PHASE1";
-       case PHASE2_START:
-               return "PHASE2_START";
-       case PHASE2_METHOD:
-               return "PHASE2_METHOD";
-       case PHASE2_MSCHAPV2_RESP:
-               return "PHASE2_MSCHAPV2_RESP";
-       case PHASE_FINISHED:
-               return "PHASE_FINISHED";
-       case SUCCESS:
-               return "SUCCESS";
-       case FAILURE:
-               return "FAILURE";
-       default:
-               return "Unknown?!";
-       }
-}
-
-
-static void eap_ttls_state(struct eap_ttls_data *data, int state)
-{
-       wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s",
-                  eap_ttls_state_txt(data->state),
-                  eap_ttls_state_txt(state));
-       data->state = state;
-}
-
-
-static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
-                            int mandatory, size_t len)
-{
-       struct ttls_avp_vendor *avp;
-       u8 flags;
-       size_t hdrlen;
-
-       avp = (struct ttls_avp_vendor *) avphdr;
-       flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
-       if (vendor_id) {
-               flags |= AVP_FLAGS_VENDOR;
-               hdrlen = sizeof(*avp);
-               avp->vendor_id = host_to_be32(vendor_id);
-       } else {
-               hdrlen = sizeof(struct ttls_avp);
-       }
-
-       avp->avp_code = host_to_be32(avp_code);
-       avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));
-
-       return avphdr + hdrlen;
-}
-
-
-static struct wpabuf * eap_ttls_avp_encapsulate(struct wpabuf *resp,
-                                               u32 avp_code, int mandatory)
-{
-       struct wpabuf *avp;
-       u8 *pos;
-
-       avp = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(resp) + 4);
-       if (avp == NULL) {
-               wpabuf_free(resp);
-               return NULL;
-       }
-
-       pos = eap_ttls_avp_hdr(wpabuf_mhead(avp), avp_code, 0, mandatory,
-                              wpabuf_len(resp));
-       os_memcpy(pos, wpabuf_head(resp), wpabuf_len(resp));
-       pos += wpabuf_len(resp);
-       AVP_PAD((const u8 *) wpabuf_head(avp), pos);
-       wpabuf_free(resp);
-       wpabuf_put(avp, pos - (u8 *) wpabuf_head(avp));
-       return avp;
-}
-
-
-struct eap_ttls_avp {
-        /* Note: eap is allocated memory; caller is responsible for freeing
-         * it. All the other pointers are pointing to the packet data, i.e.,
-         * they must not be freed separately. */
-       u8 *eap;
-       size_t eap_len;
-       u8 *user_name;
-       size_t user_name_len;
-       u8 *user_password;
-       size_t user_password_len;
-       u8 *chap_challenge;
-       size_t chap_challenge_len;
-       u8 *chap_password;
-       size_t chap_password_len;
-       u8 *mschap_challenge;
-       size_t mschap_challenge_len;
-       u8 *mschap_response;
-       size_t mschap_response_len;
-       u8 *mschap2_response;
-       size_t mschap2_response_len;
-};
-
-
-static int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse)
-{
-       struct ttls_avp *avp;
-       u8 *pos;
-       int left;
-
-       pos = wpabuf_mhead(buf);
-       left = wpabuf_len(buf);
-       os_memset(parse, 0, sizeof(*parse));
-
-       while (left > 0) {
-               u32 avp_code, avp_length, vendor_id = 0;
-               u8 avp_flags, *dpos;
-               size_t pad, dlen;
-               avp = (struct ttls_avp *) pos;
-               avp_code = be_to_host32(avp->avp_code);
-               avp_length = be_to_host32(avp->avp_length);
-               avp_flags = (avp_length >> 24) & 0xff;
-               avp_length &= 0xffffff;
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
-                          "length=%d", (int) avp_code, avp_flags,
-                          (int) avp_length);
-               if ((int) avp_length > left) {
-                       wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
-                                  "(len=%d, left=%d) - dropped",
-                                  (int) avp_length, left);
-                       goto fail;
-               }
-               if (avp_length < sizeof(*avp)) {
-                       wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length "
-                                  "%d", avp_length);
-                       goto fail;
-               }
-               dpos = (u8 *) (avp + 1);
-               dlen = avp_length - sizeof(*avp);
-               if (avp_flags & AVP_FLAGS_VENDOR) {
-                       if (dlen < 4) {
-                               wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP "
-                                          "underflow");
-                               goto fail;
-                       }
-                       vendor_id = be_to_host32(* (be32 *) dpos);
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
-                                  (int) vendor_id);
-                       dpos += 4;
-                       dlen -= 4;
-               }
-
-               wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
-
-               if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
-                       if (parse->eap == NULL) {
-                               parse->eap = os_malloc(dlen);
-                               if (parse->eap == NULL) {
-                                       wpa_printf(MSG_WARNING, "EAP-TTLS: "
-                                                  "failed to allocate memory "
-                                                  "for Phase 2 EAP data");
-                                       goto fail;
-                               }
-                               os_memcpy(parse->eap, dpos, dlen);
-                               parse->eap_len = dlen;
-                       } else {
-                               u8 *neweap = os_realloc(parse->eap,
-                                                       parse->eap_len + dlen);
-                               if (neweap == NULL) {
-                                       wpa_printf(MSG_WARNING, "EAP-TTLS: "
-                                                  "failed to allocate memory "
-                                                  "for Phase 2 EAP data");
-                                       goto fail;
-                               }
-                               os_memcpy(neweap + parse->eap_len, dpos, dlen);
-                               parse->eap = neweap;
-                               parse->eap_len += dlen;
-                       }
-               } else if (vendor_id == 0 &&
-                          avp_code == RADIUS_ATTR_USER_NAME) {
-                       wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name",
-                                         dpos, dlen);
-                       parse->user_name = dpos;
-                       parse->user_name_len = dlen;
-               } else if (vendor_id == 0 &&
-                          avp_code == RADIUS_ATTR_USER_PASSWORD) {
-                       u8 *password = dpos;
-                       size_t password_len = dlen;
-                       while (password_len > 0 &&
-                              password[password_len - 1] == '\0') {
-                               password_len--;
-                       }
-                       wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: "
-                                             "User-Password (PAP)",
-                                             password, password_len);
-                       parse->user_password = password;
-                       parse->user_password_len = password_len;
-               } else if (vendor_id == 0 &&
-                          avp_code == RADIUS_ATTR_CHAP_CHALLENGE) {
-                       wpa_hexdump(MSG_DEBUG,
-                                   "EAP-TTLS: CHAP-Challenge (CHAP)",
-                                   dpos, dlen);
-                       parse->chap_challenge = dpos;
-                       parse->chap_challenge_len = dlen;
-               } else if (vendor_id == 0 &&
-                          avp_code == RADIUS_ATTR_CHAP_PASSWORD) {
-                       wpa_hexdump(MSG_DEBUG,
-                                   "EAP-TTLS: CHAP-Password (CHAP)",
-                                   dpos, dlen);
-                       parse->chap_password = dpos;
-                       parse->chap_password_len = dlen;
-               } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
-                          avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) {
-                       wpa_hexdump(MSG_DEBUG,
-                                   "EAP-TTLS: MS-CHAP-Challenge",
-                                   dpos, dlen);
-                       parse->mschap_challenge = dpos;
-                       parse->mschap_challenge_len = dlen;
-               } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
-                          avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) {
-                       wpa_hexdump(MSG_DEBUG,
-                                   "EAP-TTLS: MS-CHAP-Response (MSCHAP)",
-                                   dpos, dlen);
-                       parse->mschap_response = dpos;
-                       parse->mschap_response_len = dlen;
-               } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
-                          avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) {
-                       wpa_hexdump(MSG_DEBUG,
-                                   "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)",
-                                   dpos, dlen);
-                       parse->mschap2_response = dpos;
-                       parse->mschap2_response_len = dlen;
-               } else if (avp_flags & AVP_FLAGS_MANDATORY) {
-                       wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported "
-                                  "mandatory AVP code %d vendor_id %d - "
-                                  "dropped", (int) avp_code, (int) vendor_id);
-                       goto fail;
-               } else {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported "
-                                  "AVP code %d vendor_id %d",
-                                  (int) avp_code, (int) vendor_id);
-               }
-
-               pad = (4 - (avp_length & 3)) & 3;
-               pos += avp_length + pad;
-               left -= avp_length + pad;
-       }
-
-       return 0;
-
-fail:
-       os_free(parse->eap);
-       parse->eap = NULL;
-       return -1;
-}
-
-
-static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
-                                       struct eap_ttls_data *data, size_t len)
-{
-       struct tls_keys keys;
-       u8 *challenge, *rnd;
-
-       if (data->ttls_version == 0) {
-               return eap_server_tls_derive_key(sm, &data->ssl,
-                                                "ttls challenge", len);
-       }
-
-       os_memset(&keys, 0, sizeof(keys));
-       if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
-           keys.client_random == NULL || keys.server_random == NULL ||
-           keys.inner_secret == NULL) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
-                          "client random, or server random to derive "
-                          "implicit challenge");
-               return NULL;
-       }
-
-       rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-       challenge = os_malloc(len);
-       if (rnd == NULL || challenge == NULL) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
-                          "challenge derivation");
-               os_free(rnd);
-               os_free(challenge);
-               return NULL;
-       }
-       os_memcpy(rnd, keys.server_random, keys.server_random_len);
-       os_memcpy(rnd + keys.server_random_len, keys.client_random,
-                 keys.client_random_len);
-
-       if (tls_prf(keys.inner_secret, keys.inner_secret_len,
-                   "inner application challenge", rnd,
-                   keys.client_random_len + keys.server_random_len,
-                   challenge, len)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
-                          "challenge");
-               os_free(rnd);
-               os_free(challenge);
-               return NULL;
-       }
-
-       os_free(rnd);
-
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
-                       challenge, len);
-
-       return challenge;
-}
-
-
-static void * eap_ttls_init(struct eap_sm *sm)
-{
-       struct eap_ttls_data *data;
-
-       data = os_zalloc(sizeof(*data));
-       if (data == NULL)
-               return NULL;
-       data->ttls_version = EAP_TTLS_VERSION;
-       data->force_version = -1;
-       if (sm->user && sm->user->force_version >= 0) {
-               data->force_version = sm->user->force_version;
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: forcing version %d",
-                          data->force_version);
-               data->ttls_version = data->force_version;
-       }
-       data->state = START;
-
-       if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
-           data->ttls_version > 0) {
-               if (data->force_version > 0) {
-                       wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
-                                  "TLS library does not support TLS/IA.",
-                                  data->force_version);
-                       eap_ttls_reset(sm, data);
-                       return NULL;
-               }
-               data->ttls_version = 0;
-       }
-
-       if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
-               eap_ttls_reset(sm, data);
-               return NULL;
-       }
-
-       return data;
-}
-
-
-static void eap_ttls_reset(struct eap_sm *sm, void *priv)
-{
-       struct eap_ttls_data *data = priv;
-       if (data == NULL)
-               return;
-       if (data->phase2_priv && data->phase2_method)
-               data->phase2_method->reset(sm, data->phase2_priv);
-       eap_server_tls_ssl_deinit(sm, &data->ssl);
-       wpabuf_free(data->pending_phase2_eap_resp);
-       os_free(data);
-}
-
-
-static struct wpabuf * eap_ttls_build_start(struct eap_sm *sm,
-                                           struct eap_ttls_data *data, u8 id)
-{      
-       struct wpabuf *req;
-
-       req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1,
-                           EAP_CODE_REQUEST, id);
-       if (req == NULL) {
-               wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for"
-                          " request");
-               eap_ttls_state(data, FAILURE);
-               return NULL;
-       }
-
-       wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->ttls_version);
-
-       eap_ttls_state(data, PHASE1);
-
-       return req;
-}
-
-
-static struct wpabuf * eap_ttls_build_phase2_eap_req(
-       struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
-{
-       struct wpabuf *buf, *encr_req;
-
-
-       buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
-       if (buf == NULL)
-               return NULL;
-
-       wpa_hexdump_buf_key(MSG_DEBUG,
-                           "EAP-TTLS/EAP: Encapsulate Phase 2 data", buf);
-
-       buf = eap_ttls_avp_encapsulate(buf, RADIUS_ATTR_EAP_MESSAGE, 1);
-       if (buf == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate "
-                          "packet");
-               return NULL;
-       }
-
-       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
-                           "Phase 2 data", buf);
-
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
-       wpabuf_free(buf);
-
-       return encr_req;
-}
-
-
-static struct wpabuf * eap_ttls_build_phase2_mschapv2(
-       struct eap_sm *sm, struct eap_ttls_data *data)
-{
-       struct wpabuf *encr_req, msgbuf;
-       u8 *req, *pos, *end;
-       int ret;
-
-       pos = req = os_malloc(100);
-       if (req == NULL)
-               return NULL;
-       end = req + 100;
-
-       if (data->mschapv2_resp_ok) {
-               pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS,
-                                      RADIUS_VENDOR_ID_MICROSOFT, 1, 43);
-               *pos++ = data->mschapv2_ident;
-               ret = os_snprintf((char *) pos, end - pos, "S=");
-               if (ret >= 0 && ret < end - pos)
-                       pos += ret;
-               pos += wpa_snprintf_hex_uppercase(
-                       (char *) pos, end - pos, data->mschapv2_auth_response,
-                       sizeof(data->mschapv2_auth_response));
-       } else {
-               pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR,
-                                      RADIUS_VENDOR_ID_MICROSOFT, 1, 6);
-               os_memcpy(pos, "Failed", 6);
-               pos += 6;
-               AVP_PAD(req, pos);
-       }
-
-       wpabuf_set(&msgbuf, req, pos - req);
-       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
-                           "data", &msgbuf);
-
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
-       os_free(req);
-
-       return encr_req;
-}
-
-
-static struct wpabuf * eap_ttls_build_phase_finished(
-       struct eap_sm *sm, struct eap_ttls_data *data, int final)
-{
-       return tls_connection_ia_send_phase_finished(sm->ssl_ctx,
-                                                    data->ssl.conn, final);
-}
-
-
-static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
-{
-       struct eap_ttls_data *data = priv;
-
-       if (data->ssl.state == FRAG_ACK) {
-               return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
-                                               data->ttls_version);
-       }
-
-       if (data->ssl.state == WAIT_FRAG_ACK) {
-               return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
-                                               data->ttls_version, id);
-       }
-
-       switch (data->state) {
-       case START:
-               return eap_ttls_build_start(sm, data, id);
-       case PHASE1:
-               if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, "
-                                  "starting Phase2");
-                       eap_ttls_state(data, PHASE2_START);
-               }
-               break;
-       case PHASE2_METHOD:
-               wpabuf_free(data->ssl.tls_out);
-               data->ssl.tls_out_pos = 0;
-               data->ssl.tls_out = eap_ttls_build_phase2_eap_req(sm, data,
-                                                                 id);
-               break;
-       case PHASE2_MSCHAPV2_RESP:
-               wpabuf_free(data->ssl.tls_out);
-               data->ssl.tls_out_pos = 0;
-               data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data);
-               break;
-       case PHASE_FINISHED:
-               wpabuf_free(data->ssl.tls_out);
-               data->ssl.tls_out_pos = 0;
-               data->ssl.tls_out = eap_ttls_build_phase_finished(sm, data, 1);
-               break;
-       default:
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
-                          __func__, data->state);
-               return NULL;
-       }
-
-       return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
-                                       data->ttls_version, id);
-}
-
-
-static Boolean eap_ttls_check(struct eap_sm *sm, void *priv,
-                             struct wpabuf *respData)
-{
-       const u8 *pos;
-       size_t len;
-
-       pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len);
-       if (pos == NULL || len < 1) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame");
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-
-static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
-                                           struct eap_ttls_data *data,
-                                           const u8 *key, size_t key_len)
-{
-       u8 *buf;
-       size_t buf_len;
-       int ret;
-
-       if (key) {
-               buf_len = 2 + key_len;
-               buf = os_malloc(buf_len);
-               if (buf == NULL)
-                       return -1;
-               WPA_PUT_BE16(buf, key_len);
-               os_memcpy(buf + 2, key, key_len);
-       } else {
-               buf = NULL;
-               buf_len = 0;
-       }
-
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
-                       "secret permutation", buf, buf_len);
-       ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
-                                                    data->ssl.conn,
-                                                    buf, buf_len);
-       os_free(buf);
-
-       return ret;
-}
-
-
-static void eap_ttls_process_phase2_pap(struct eap_sm *sm,
-                                       struct eap_ttls_data *data,
-                                       const u8 *user_password,
-                                       size_t user_password_len)
-{
-       if (!sm->user || !sm->user->password || sm->user->password_hash ||
-           !(sm->user->ttls_auth & EAP_TTLS_AUTH_PAP)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user "
-                          "password configured");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (sm->user->password_len != user_password_len ||
-           os_memcmp(sm->user->password, user_password, user_password_len) !=
-           0) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password");
-       eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
-                      SUCCESS);
-}
-
-
-static void eap_ttls_process_phase2_chap(struct eap_sm *sm,
-                                        struct eap_ttls_data *data,
-                                        const u8 *challenge,
-                                        size_t challenge_len,
-                                        const u8 *password,
-                                        size_t password_len)
-{
-       u8 *chal, hash[CHAP_MD5_LEN];
-
-       if (challenge == NULL || password == NULL ||
-           challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN ||
-           password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes "
-                          "(challenge len %lu password len %lu)",
-                          (unsigned long) challenge_len,
-                          (unsigned long) password_len);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (!sm->user || !sm->user->password || sm->user->password_hash ||
-           !(sm->user->ttls_auth & EAP_TTLS_AUTH_CHAP)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user "
-                          "password configured");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       chal = eap_ttls_implicit_challenge(sm, data,
-                                          EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
-       if (chal == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate "
-                          "challenge from TLS data");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 ||
-           password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch");
-               os_free(chal);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-       os_free(chal);
-
-       /* MD5(Ident + Password + Challenge) */
-       chap_md5(password[0], sm->user->password, sm->user->password_len,
-                challenge, challenge_len, hash);
-
-       if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
-               eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
-                              SUCCESS);
-       } else {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password");
-               eap_ttls_state(data, FAILURE);
-       }
-}
-
-
-static void eap_ttls_process_phase2_mschap(struct eap_sm *sm,
-                                          struct eap_ttls_data *data,
-                                          u8 *challenge, size_t challenge_len,
-                                          u8 *response, size_t response_len)
-{
-       u8 *chal, nt_response[24];
-
-       if (challenge == NULL || response == NULL ||
-           challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN ||
-           response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP "
-                          "attributes (challenge len %lu response len %lu)",
-                          (unsigned long) challenge_len,
-                          (unsigned long) response_len);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (!sm->user || !sm->user->password ||
-           !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password "
-                          "configured");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       chal = eap_ttls_implicit_challenge(sm, data,
-                                          EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
-       if (chal == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate "
-                          "challenge from TLS data");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 ||
-           response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch");
-               os_free(chal);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-       os_free(chal);
-
-       if (sm->user->password_hash)
-               challenge_response(challenge, sm->user->password, nt_response);
-       else
-               nt_challenge_response(challenge, sm->user->password,
-                                     sm->user->password_len, nt_response);
-
-       if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
-               eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
-                              SUCCESS);
-       } else {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response");
-               wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received",
-                           response + 2 + 24, 24);
-               wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected",
-                           nt_response, 24);
-               eap_ttls_state(data, FAILURE);
-       }
-}
-
-
-static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
-                                            struct eap_ttls_data *data,
-                                            u8 *challenge,
-                                            size_t challenge_len,
-                                            u8 *response, size_t response_len)
-{
-       u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge,
-               *auth_challenge;
-       size_t username_len, i;
-
-       if (challenge == NULL || response == NULL ||
-           challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN ||
-           response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 "
-                          "attributes (challenge len %lu response len %lu)",
-                          (unsigned long) challenge_len,
-                          (unsigned long) response_len);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (!sm->user || !sm->user->password ||
-           !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password "
-                          "configured");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       /* MSCHAPv2 does not include optional domain name in the
-        * challenge-response calculation, so remove domain prefix
-        * (if present). */
-       username = sm->identity;
-       username_len = sm->identity_len;
-       for (i = 0; i < username_len; i++) {
-               if (username[i] == '\\') {
-                       username_len -= i + 1;
-                       username += i + 1;
-                       break;
-               }
-       }
-
-       chal = eap_ttls_implicit_challenge(
-               sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
-       if (chal == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate "
-                          "challenge from TLS data");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 ||
-           response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
-               os_free(chal);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-       os_free(chal);
-
-       auth_challenge = challenge;
-       peer_challenge = response + 2;
-
-       wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User",
-                         username, username_len);
-       wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge",
-                   auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
-       wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge",
-                   peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
-
-       if (sm->user->password_hash) {
-               generate_nt_response_pwhash(auth_challenge, peer_challenge,
-                                           username, username_len,
-                                           sm->user->password,
-                                           nt_response);
-       } else {
-               generate_nt_response(auth_challenge, peer_challenge,
-                                    username, username_len,
-                                    sm->user->password,
-                                    sm->user->password_len,
-                                    nt_response);
-       }
-
-       rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
-       if (os_memcmp(nt_response, rx_resp, 24) == 0) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
-                          "NT-Response");
-               data->mschapv2_resp_ok = 1;
-               if (data->ttls_version > 0) {
-                       const u8 *pw_hash;
-                       u8 pw_hash_buf[16], pw_hash_hash[16], master_key[16];
-                       u8 session_key[2 * MSCHAPV2_KEY_LEN];
-
-                       if (sm->user->password_hash)
-                               pw_hash = sm->user->password;
-                       else {
-                               nt_password_hash(sm->user->password,
-                                                sm->user->password_len,
-                                                pw_hash_buf);
-                               pw_hash = pw_hash_buf;
-                       }
-                       hash_nt_password_hash(pw_hash, pw_hash_hash);
-                       get_master_key(pw_hash_hash, nt_response, master_key);
-                       get_asymetric_start_key(master_key, session_key,
-                                               MSCHAPV2_KEY_LEN, 0, 0);
-                       get_asymetric_start_key(master_key,
-                                               session_key + MSCHAPV2_KEY_LEN,
-                                               MSCHAPV2_KEY_LEN, 1, 0);
-                       eap_ttls_ia_permute_inner_secret(sm, data,
-                                                        session_key,
-                                                        sizeof(session_key));
-               }
-
-               if (sm->user->password_hash) {
-                       generate_authenticator_response_pwhash(
-                               sm->user->password,
-                               peer_challenge, auth_challenge,
-                               username, username_len, nt_response,
-                               data->mschapv2_auth_response);
-               } else {
-                       generate_authenticator_response(
-                               sm->user->password, sm->user->password_len,
-                               peer_challenge, auth_challenge,
-                               username, username_len, nt_response,
-                               data->mschapv2_auth_response);
-               }
-       } else {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid "
-                          "NT-Response");
-               wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received",
-                           rx_resp, 24);
-               wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected",
-                           nt_response, 24);
-               data->mschapv2_resp_ok = 0;
-       }
-       eap_ttls_state(data, PHASE2_MSCHAPV2_RESP);
-       data->mschapv2_ident = response[0];
-}
-
-
-static int eap_ttls_phase2_eap_init(struct eap_sm *sm,
-                                   struct eap_ttls_data *data,
-                                   EapType eap_type)
-{
-       if (data->phase2_priv && data->phase2_method) {
-               data->phase2_method->reset(sm, data->phase2_priv);
-               data->phase2_method = NULL;
-               data->phase2_priv = NULL;
-       }
-       data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
-                                                       eap_type);
-       if (!data->phase2_method)
-               return -1;
-
-       sm->init_phase2 = 1;
-       data->phase2_priv = data->phase2_method->init(sm);
-       sm->init_phase2 = 0;
-       return data->phase2_priv == NULL ? -1 : 0;
-}
-
-
-static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,
-                                                struct eap_ttls_data *data,
-                                                u8 *in_data, size_t in_len)
-{
-       u8 next_type = EAP_TYPE_NONE;
-       struct eap_hdr *hdr;
-       u8 *pos;
-       size_t left;
-       struct wpabuf buf;
-       const struct eap_method *m = data->phase2_method;
-       void *priv = data->phase2_priv;
-
-       if (priv == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not "
-                          "initialized?!", __func__);
-               return;
-       }
-
-       hdr = (struct eap_hdr *) in_data;
-       pos = (u8 *) (hdr + 1);
-
-       if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
-               left = in_len - sizeof(*hdr);
-               wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; "
-                           "allowed types", pos + 1, left - 1);
-               eap_sm_process_nak(sm, pos + 1, left - 1);
-               if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
-                   sm->user->methods[sm->user_eap_method_index].method !=
-                   EAP_TYPE_NONE) {
-                       next_type = sm->user->methods[
-                               sm->user_eap_method_index++].method;
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d",
-                                  next_type);
-                       if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
-                               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to "
-                                          "initialize EAP type %d",
-                                          next_type);
-                               eap_ttls_state(data, FAILURE);
-                               return;
-                       }
-               } else {
-                       eap_ttls_state(data, FAILURE);
-               }
-               return;
-       }
-
-       wpabuf_set(&buf, in_data, in_len);
-
-       if (m->check(sm, priv, &buf)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to "
-                          "ignore the packet");
-               return;
-       }
-
-       m->process(sm, priv, &buf);
-
-       if (sm->method_pending == METHOD_PENDING_WAIT) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in "
-                          "pending wait state - save decrypted response");
-               wpabuf_free(data->pending_phase2_eap_resp);
-               data->pending_phase2_eap_resp = wpabuf_dup(&buf);
-       }
-
-       if (!m->isDone(sm, priv))
-               return;
-
-       if (!m->isSuccess(sm, priv)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       switch (data->state) {
-       case PHASE2_START:
-               if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
-                       wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 "
-                                         "Identity not found in the user "
-                                         "database",
-                                         sm->identity, sm->identity_len);
-                       eap_ttls_state(data, FAILURE);
-                       break;
-               }
-
-               eap_ttls_state(data, PHASE2_METHOD);
-               next_type = sm->user->methods[0].method;
-               sm->user_eap_method_index = 1;
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type);
-               if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize "
-                                  "EAP type %d", next_type);
-                       eap_ttls_state(data, FAILURE);
-               }
-               break;
-       case PHASE2_METHOD:
-               if (data->ttls_version > 0) {
-                       if (m->getKey) {
-                               u8 *key;
-                               size_t key_len;
-                               key = m->getKey(sm, priv, &key_len);
-                               eap_ttls_ia_permute_inner_secret(sm, data,
-                                                                key, key_len);
-                       }
-                       eap_ttls_state(data, PHASE_FINISHED);
-               } else
-                       eap_ttls_state(data, SUCCESS);
-               break;
-       case FAILURE:
-               break;
-       default:
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
-                          __func__, data->state);
-               break;
-       }
-}
-
-
-static void eap_ttls_process_phase2_eap(struct eap_sm *sm,
-                                       struct eap_ttls_data *data,
-                                       const u8 *eap, size_t eap_len)
-{
-       struct eap_hdr *hdr;
-       size_t len;
-
-       if (data->state == PHASE2_START) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2");
-               if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0)
-               {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "
-                                  "initialize EAP-Identity");
-                       return;
-               }
-       }
-
-       if (eap_len < sizeof(*hdr)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP "
-                          "packet (len=%lu)", (unsigned long) eap_len);
-               return;
-       }
-
-       hdr = (struct eap_hdr *) eap;
-       len = be_to_host16(hdr->length);
-       wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "
-                  "identifier=%d length=%lu", hdr->code, hdr->identifier,
-                  (unsigned long) len);
-       if (len > eap_len) {
-               wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2"
-                          " EAP frame (hdr len=%lu, data len in AVP=%lu)",
-                          (unsigned long) len, (unsigned long) eap_len);
-               return;
-       }
-
-       switch (hdr->code) {
-       case EAP_CODE_RESPONSE:
-               eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr,
-                                                    len);
-               break;
-       default:
-               wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in "
-                          "Phase 2 EAP header", hdr->code);
-               break;
-       }
-}
-
-
-static void eap_ttls_process_phase2(struct eap_sm *sm,
-                                   struct eap_ttls_data *data,
-                                   struct wpabuf *in_buf)
-{
-       struct wpabuf *in_decrypted;
-       struct eap_ttls_avp parse;
-
-       wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
-                  " Phase 2", (unsigned long) wpabuf_len(in_buf));
-
-       if (data->pending_phase2_eap_resp) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
-                          "- skip decryption and use old data");
-               eap_ttls_process_phase2_eap(
-                       sm, data, wpabuf_head(data->pending_phase2_eap_resp),
-                       wpabuf_len(data->pending_phase2_eap_resp));
-               wpabuf_free(data->pending_phase2_eap_resp);
-               data->pending_phase2_eap_resp = NULL;
-               return;
-       }
-
-       in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-                                             in_buf);
-       if (in_decrypted == NULL) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
-                          "data");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (data->state == PHASE_FINISHED) {
-               if (wpabuf_len(in_decrypted) == 0 &&
-                   tls_connection_ia_final_phase_finished(sm->ssl_ctx,
-                                                          data->ssl.conn)) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
-                                  "received");
-                       eap_ttls_state(data, SUCCESS);
-               } else {
-                       wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid "
-                                  "FinalPhaseFinished");
-                       eap_ttls_state(data, FAILURE);
-               }
-
-               wpabuf_free(in_decrypted);
-               return;
-       }
-
-       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
-                           in_decrypted);
-
-       if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
-               wpabuf_free(in_decrypted);
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       if (parse.user_name) {
-               os_free(sm->identity);
-               sm->identity = os_malloc(parse.user_name_len);
-               if (sm->identity) {
-                       os_memcpy(sm->identity, parse.user_name,
-                                 parse.user_name_len);
-                       sm->identity_len = parse.user_name_len;
-               }
-               if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1)
-                   != 0) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not "
-                                  "found in the user database");
-                       eap_ttls_state(data, FAILURE);
-                       goto done;
-               }
-       }
-
-#ifdef EAP_SERVER_TNC
-       if (data->tnc_started && parse.eap == NULL) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP "
-                          "response from peer");
-               eap_ttls_state(data, FAILURE);
-               goto done;
-       }
-#endif /* EAP_SERVER_TNC */
-
-       if (parse.eap) {
-               eap_ttls_process_phase2_eap(sm, data, parse.eap,
-                                           parse.eap_len);
-       } else if (parse.user_password) {
-               eap_ttls_process_phase2_pap(sm, data, parse.user_password,
-                                           parse.user_password_len);
-       } else if (parse.chap_password) {
-               eap_ttls_process_phase2_chap(sm, data,
-                                            parse.chap_challenge,
-                                            parse.chap_challenge_len,
-                                            parse.chap_password,
-                                            parse.chap_password_len);
-       } else if (parse.mschap_response) {
-               eap_ttls_process_phase2_mschap(sm, data,
-                                              parse.mschap_challenge,
-                                              parse.mschap_challenge_len,
-                                              parse.mschap_response,
-                                              parse.mschap_response_len);
-       } else if (parse.mschap2_response) {
-               eap_ttls_process_phase2_mschapv2(sm, data,
-                                                parse.mschap_challenge,
-                                                parse.mschap_challenge_len,
-                                                parse.mschap2_response,
-                                                parse.mschap2_response_len);
-       }
-
-done:
-       wpabuf_free(in_decrypted);
-       os_free(parse.eap);
-}
-
-
-static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
-{
-#ifdef EAP_SERVER_TNC
-       if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
-               return;
-
-       wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC");
-       if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC");
-               eap_ttls_state(data, FAILURE);
-               return;
-       }
-
-       data->tnc_started = 1;
-       eap_ttls_state(data, PHASE2_METHOD);
-#endif /* EAP_SERVER_TNC */
-}
-
-
-static int eap_ttls_process_version(struct eap_sm *sm, void *priv,
-                                   int peer_version)
-{
-       struct eap_ttls_data *data = priv;
-       if (peer_version < data->ttls_version) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
-                          "use version %d",
-                          peer_version, data->ttls_version, peer_version);
-               data->ttls_version = peer_version;
-       }
-
-       if (data->ttls_version > 0 && !data->tls_ia_configured) {
-               if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
-                       wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
-                                  "TLS/IA");
-                       return -1;
-               }
-               data->tls_ia_configured = 1;
-       }
-
-       return 0;
-}
-
-
-static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
-                                const struct wpabuf *respData)
-{
-       struct eap_ttls_data *data = priv;
-
-       switch (data->state) {
-       case PHASE1:
-               if (eap_server_tls_phase1(sm, &data->ssl) < 0)
-                       eap_ttls_state(data, FAILURE);
-               break;
-       case PHASE2_START:
-       case PHASE2_METHOD:
-       case PHASE_FINISHED:
-               eap_ttls_process_phase2(sm, data, data->ssl.tls_in);
-               eap_ttls_start_tnc(sm, data);
-               break;
-       case PHASE2_MSCHAPV2_RESP:
-               if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) ==
-                   0) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
-                                  "acknowledged response");
-                       eap_ttls_state(data, data->ttls_version > 0 ?
-                                      PHASE_FINISHED : SUCCESS);
-               } else if (!data->mschapv2_resp_ok) {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
-                                  "acknowledged error");
-                       eap_ttls_state(data, FAILURE);
-               } else {
-                       wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
-                                  "frame from peer (payload len %lu, "
-                                  "expected empty frame)",
-                                  (unsigned long)
-                                  wpabuf_len(data->ssl.tls_in));
-                       eap_ttls_state(data, FAILURE);
-               }
-               eap_ttls_start_tnc(sm, data);
-               break;
-       default:
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",
-                          data->state, __func__);
-               break;
-       }
-}
-
-
-static void eap_ttls_process(struct eap_sm *sm, void *priv,
-                            struct wpabuf *respData)
-{
-       struct eap_ttls_data *data = priv;
-       if (eap_server_tls_process(sm, &data->ssl, respData, data,
-                                  EAP_TYPE_TTLS, eap_ttls_process_version,
-                                  eap_ttls_process_msg) < 0)
-               eap_ttls_state(data, FAILURE);
-}
-
-
-static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv)
-{
-       struct eap_ttls_data *data = priv;
-       return data->state == SUCCESS || data->state == FAILURE;
-}
-
-
-static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm,
-                                  struct eap_ttls_data *data)
-{
-       struct tls_keys keys;
-       u8 *rnd, *key;
-
-       os_memset(&keys, 0, sizeof(keys));
-       if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
-           keys.client_random == NULL || keys.server_random == NULL ||
-           keys.inner_secret == NULL) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
-                          "client random, or server random to derive keying "
-                          "material");
-               return NULL;
-       }
-
-       rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-       key = os_malloc(EAP_TLS_KEY_LEN);
-       if (rnd == NULL || key == NULL) {
-               wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
-               os_free(rnd);
-               os_free(key);
-               return NULL;
-       }
-       os_memcpy(rnd, keys.client_random, keys.client_random_len);
-       os_memcpy(rnd + keys.client_random_len, keys.server_random,
-                 keys.server_random_len);
-
-       if (tls_prf(keys.inner_secret, keys.inner_secret_len,
-                   "ttls v1 keying material", rnd, keys.client_random_len +
-                   keys.server_random_len, key, EAP_TLS_KEY_LEN)) {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
-               os_free(rnd);
-               os_free(key);
-               return NULL;
-       }
-
-       wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
-                   rnd, keys.client_random_len + keys.server_random_len);
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
-                       keys.inner_secret, keys.inner_secret_len);
-
-       os_free(rnd);
-
-       return key;
-}
-
-
-static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
-{
-       struct eap_ttls_data *data = priv;
-       u8 *eapKeyData;
-
-       if (data->state != SUCCESS)
-               return NULL;
-
-       if (data->ttls_version == 0) {
-               eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-                                                      "ttls keying material",
-                                                      EAP_TLS_KEY_LEN);
-       } else {
-               eapKeyData = eap_ttls_v1_derive_key(sm, data);
-       }
-
-       if (eapKeyData) {
-               *len = EAP_TLS_KEY_LEN;
-               wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
-                               eapKeyData, EAP_TLS_KEY_LEN);
-       } else {
-               wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
-       }
-
-       return eapKeyData;
-}
-
-
-static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv)
-{
-       struct eap_ttls_data *data = priv;
-       return data->state == SUCCESS;
-}
-
-
-int eap_server_ttls_register(void)
-{
-       struct eap_method *eap;
-       int ret;
-
-       eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
-                                     EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
-       if (eap == NULL)
-               return -1;
-
-       eap->init = eap_ttls_init;
-       eap->reset = eap_ttls_reset;
-       eap->buildReq = eap_ttls_buildReq;
-       eap->check = eap_ttls_check;
-       eap->process = eap_ttls_process;
-       eap->isDone = eap_ttls_isDone;
-       eap->getKey = eap_ttls_getKey;
-       eap->isSuccess = eap_ttls_isSuccess;
-
-       ret = eap_server_method_register(eap);
-       if (ret)
-               eap_server_method_free(eap);
-       return ret;
-}