eap_server_ttls.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-TTLS (RFC 5281)
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/ms_funcs.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_tls_common.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/chap.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_ttls.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define EAP_TTLS_VERSION 0
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_reset(struct eap_sm *sm, void *priv);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_ttls_data {
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ssl_data ssl;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum {
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		START, PHASE1, PHASE2_START, PHASE2_METHOD,
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		PHASE2_MSCHAPV2_RESP, SUCCESS, FAILURE
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} state;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ttls_version;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *phase2_method;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *phase2_priv;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int mschapv2_resp_ok;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 mschapv2_auth_response[20];
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 mschapv2_ident;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *pending_phase2_eap_resp;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tnc_started;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_ttls_state_txt(int state)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case START:
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "START";
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE1:
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PHASE1";
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_START:
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PHASE2_START";
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PHASE2_METHOD";
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_MSCHAPV2_RESP:
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PHASE2_MSCHAPV2_RESP";
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SUCCESS:
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SUCCESS";
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case FAILURE:
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "FAILURE";
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Unknown?!";
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_state(struct eap_ttls_data *data, int state)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s",
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eap_ttls_state_txt(data->state),
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eap_ttls_state_txt(state));
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->state = state;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     int mandatory, size_t len)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ttls_avp_vendor *avp;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t hdrlen;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	avp = (struct ttls_avp_vendor *) avphdr;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_id) {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		flags |= AVP_FLAGS_VENDOR;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdrlen = sizeof(*avp);
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp->vendor_id = host_to_be32(vendor_id);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdrlen = sizeof(struct ttls_avp);
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	avp->avp_code = host_to_be32(avp_code);
1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	avp->avp_length = host_to_be32(((u32) flags << 24) |
1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       ((u32) (hdrlen + len)));
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return avphdr + hdrlen;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_avp_encapsulate(struct wpabuf *resp,
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						u32 avp_code, int mandatory)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *avp;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	avp = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(resp) + 4);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (avp == NULL) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(resp);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_ttls_avp_hdr(wpabuf_mhead(avp), avp_code, 0, mandatory,
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       wpabuf_len(resp));
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, wpabuf_head(resp), wpabuf_len(resp));
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpabuf_len(resp);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	AVP_PAD((const u8 *) wpabuf_head(avp), pos);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(avp, pos - (u8 *) wpabuf_head(avp));
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return avp;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_ttls_avp {
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 /* Note: eap is allocated memory; caller is responsible for freeing
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  * it. All the other pointers are pointing to the packet data, i.e.,
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  * they must not be freed separately. */
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *eap;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t eap_len;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *user_name;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t user_name_len;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *user_password;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t user_password_len;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chap_challenge;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t chap_challenge_len;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chap_password;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t chap_password_len;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *mschap_challenge;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t mschap_challenge_len;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *mschap_response;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t mschap_response_len;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *mschap2_response;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t mschap2_response_len;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ttls_avp *avp;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int left;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpabuf_mhead(buf);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = wpabuf_len(buf);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(parse, 0, sizeof(*parse));
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (left > 0) {
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u32 avp_code, avp_length, vendor_id = 0;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 avp_flags, *dpos;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t pad, dlen;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp = (struct ttls_avp *) pos;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp_code = be_to_host32(avp->avp_code);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp_length = be_to_host32(avp->avp_length);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp_flags = (avp_length >> 24) & 0xff;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		avp_length &= 0xffffff;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length=%d", (int) avp_code, avp_flags,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) avp_length);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((int) avp_length > left) {
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(len=%d, left=%d) - dropped",
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) avp_length, left);
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (avp_length < sizeof(*avp)) {
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length "
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%d", avp_length);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dpos = (u8 *) (avp + 1);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = avp_length - sizeof(*avp);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (avp_flags & AVP_FLAGS_VENDOR) {
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dlen < 4) {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP "
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "underflow");
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			vendor_id = be_to_host32(* (be32 *) dpos);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) vendor_id);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dpos += 4;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dlen -= 4;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (parse->eap == NULL) {
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				parse->eap = os_malloc(dlen);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (parse->eap == NULL) {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					wpa_printf(MSG_WARNING, "EAP-TTLS: "
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "failed to allocate memory "
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "for Phase 2 EAP data");
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					goto fail;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(parse->eap, dpos, dlen);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				parse->eap_len = dlen;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u8 *neweap = os_realloc(parse->eap,
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							parse->eap_len + dlen);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (neweap == NULL) {
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					wpa_printf(MSG_WARNING, "EAP-TTLS: "
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "failed to allocate memory "
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "for Phase 2 EAP data");
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					goto fail;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(neweap + parse->eap_len, dpos, dlen);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				parse->eap = neweap;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				parse->eap_len += dlen;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == 0 &&
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_USER_NAME) {
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name",
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  dpos, dlen);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->user_name = dpos;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->user_name_len = dlen;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == 0 &&
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_USER_PASSWORD) {
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 *password = dpos;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t password_len = dlen;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (password_len > 0 &&
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       password[password_len - 1] == '\0') {
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				password_len--;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: "
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      "User-Password (PAP)",
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      password, password_len);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->user_password = password;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->user_password_len = password_len;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == 0 &&
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_CHAP_CHALLENGE) {
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG,
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-TTLS: CHAP-Challenge (CHAP)",
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    dpos, dlen);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->chap_challenge = dpos;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->chap_challenge_len = dlen;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == 0 &&
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_CHAP_PASSWORD) {
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG,
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-TTLS: CHAP-Password (CHAP)",
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    dpos, dlen);
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->chap_password = dpos;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->chap_password_len = dlen;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG,
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-TTLS: MS-CHAP-Challenge",
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    dpos, dlen);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap_challenge = dpos;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap_challenge_len = dlen;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) {
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-TTLS: MS-CHAP-Response (MSCHAP)",
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    dpos, dlen);
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap_response = dpos;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap_response_len = dlen;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) {
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)",
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    dpos, dlen);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap2_response = dpos;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			parse->mschap2_response_len = dlen;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (avp_flags & AVP_FLAGS_MANDATORY) {
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported "
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "mandatory AVP code %d vendor_id %d - "
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "dropped", (int) avp_code, (int) vendor_id);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported "
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "AVP code %d vendor_id %d",
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) avp_code, (int) vendor_id);
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pad = (4 - (avp_length & 3)) & 3;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += avp_length + pad;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left -= avp_length + pad;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(parse->eap);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parse->eap = NULL;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct eap_ttls_data *data, size_t len)
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return eap_server_tls_derive_key(sm, &data->ssl, "ttls challenge",
3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					 len);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_ttls_init(struct eap_sm *sm)
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ttls_version = EAP_TTLS_VERSION;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->state = START;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_reset(sm, data);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_reset(struct eap_sm *sm, void *priv)
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->phase2_priv && data->phase2_method)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_method->reset(sm, data->phase2_priv);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_tls_ssl_deinit(sm, &data->ssl);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(data->pending_phase2_eap_resp);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_start(struct eap_sm *sm,
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct eap_ttls_data *data, u8 id)
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1,
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    EAP_CODE_REQUEST, id);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for"
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " request");
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->ttls_version);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_ttls_state(data, PHASE1);
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_phase2_eap_req(
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf, *encr_req;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_DEBUG,
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "EAP-TTLS/EAP: Encapsulate Phase 2 data", buf);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = eap_ttls_avp_encapsulate(buf, RADIUS_ATTR_EAP_MESSAGE, 1);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate "
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "packet");
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "Phase 2 data", buf);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return encr_req;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_phase2_mschapv2(
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm, struct eap_ttls_data *data)
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *encr_req, msgbuf;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *req, *pos, *end;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = req = os_malloc(100);
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = req + 100;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->mschapv2_resp_ok) {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS,
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       RADIUS_VENDOR_ID_MICROSOFT, 1, 43);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = data->mschapv2_ident;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf((char *) pos, end - pos, "S=");
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret >= 0 && ret < end - pos)
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ret;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += wpa_snprintf_hex_uppercase(
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(char *) pos, end - pos, data->mschapv2_auth_response,
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sizeof(data->mschapv2_auth_response));
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR,
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       RADIUS_VENDOR_ID_MICROSOFT, 1, 6);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos, "Failed", 6);
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 6;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		AVP_PAD(req, pos);
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_set(&msgbuf, req, pos - req);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "data", &msgbuf);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(req);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return encr_req;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->ssl.state == FRAG_ACK) {
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						data->ttls_version);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->ssl.state == WAIT_FRAG_ACK) {
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						data->ttls_version, id);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->state) {
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case START:
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_ttls_build_start(sm, data, id);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE1:
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, "
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "starting Phase2");
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, PHASE2_START);
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->ssl.tls_out);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ssl.tls_out_pos = 0;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ssl.tls_out = eap_ttls_build_phase2_eap_req(sm, data,
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt								  id);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_MSCHAPV2_RESP:
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->ssl.tls_out);
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ssl.tls_out_pos = 0;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, data->state);
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->ttls_version, id);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_check(struct eap_sm *sm, void *priv,
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct wpabuf *respData)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len);
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL || len < 1) {
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame");
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return FALSE;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_pap(struct eap_sm *sm,
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct eap_ttls_data *data,
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *user_password,
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					size_t user_password_len)
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password || sm->user->password_hash ||
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_PAP)) {
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user "
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "password configured");
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->password_len != user_password_len ||
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(sm->user->password, user_password, user_password_len) !=
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password");
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password");
5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_ttls_state(data, SUCCESS);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_chap(struct eap_sm *sm,
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct eap_ttls_data *data,
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *challenge,
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 size_t challenge_len,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *password,
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 size_t password_len)
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chal, hash[CHAP_MD5_LEN];
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge == NULL || password == NULL ||
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN ||
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) {
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes "
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(challenge len %lu password len %lu)",
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) challenge_len,
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) password_len);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password || sm->user->password_hash ||
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_CHAP)) {
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user "
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "password configured");
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chal = eap_ttls_implicit_challenge(sm, data,
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chal == NULL) {
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate "
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "challenge from TLS data");
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 ||
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) {
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch");
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* MD5(Ident + Password + Challenge) */
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chap_md5(password[0], sm->user->password, sm->user->password_len,
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 challenge, challenge_len, hash);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) {
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password");
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschap(struct eap_sm *sm,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   struct eap_ttls_data *data,
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *challenge, size_t challenge_len,
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *response, size_t response_len)
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chal, nt_response[24];
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge == NULL || response == NULL ||
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN ||
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) {
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP "
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attributes (challenge len %lu response len %lu)",
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) challenge_len,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) response_len);
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password ||
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) {
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password "
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configured");
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chal = eap_ttls_implicit_challenge(sm, data,
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chal == NULL) {
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate "
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "challenge from TLS data");
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 ||
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch");
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->password_hash)
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		challenge_response(challenge, sm->user->password, nt_response);
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nt_challenge_response(challenge, sm->user->password,
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      sm->user->password_len, nt_response);
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) {
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
6421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response");
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received",
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    response + 2 + 24, 24);
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected",
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    nt_response, 24);
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct eap_ttls_data *data,
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *challenge,
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t challenge_len,
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *response, size_t response_len)
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*auth_challenge;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t username_len, i;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge == NULL || response == NULL ||
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN ||
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) {
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 "
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attributes (challenge len %lu response len %lu)",
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) challenge_len,
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) response_len);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password ||
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) {
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password "
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configured");
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* MSCHAPv2 does not include optional domain name in the
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * challenge-response calculation, so remove domain prefix
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (if present). */
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	username = sm->identity;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	username_len = sm->identity_len;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < username_len; i++) {
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (username[i] == '\\') {
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			username_len -= i + 1;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			username += i + 1;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chal = eap_ttls_implicit_challenge(
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chal == NULL) {
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate "
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "challenge from TLS data");
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 ||
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) {
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	auth_challenge = challenge;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer_challenge = response + 2;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User",
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  username, username_len);
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge",
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge",
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->password_hash) {
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generate_nt_response_pwhash(auth_challenge, peer_challenge,
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    username, username_len,
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sm->user->password,
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    nt_response);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generate_nt_response(auth_challenge, peer_challenge,
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     username, username_len,
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     sm->user->password,
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     sm->user->password_len,
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     nt_response);
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(nt_response, rx_resp, 24) == 0) {
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NT-Response");
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->mschapv2_resp_ok = 1;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user->password_hash) {
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			generate_authenticator_response_pwhash(
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user->password,
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				peer_challenge, auth_challenge,
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				username, username_len, nt_response,
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->mschapv2_auth_response);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			generate_authenticator_response(
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user->password, sm->user->password_len,
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				peer_challenge, auth_challenge,
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				username, username_len, nt_response,
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->mschapv2_auth_response);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid "
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NT-Response");
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received",
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rx_resp, 24);
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected",
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    nt_response, 24);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->mschapv2_resp_ok = 0;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_ttls_state(data, PHASE2_MSCHAPV2_RESP);
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->mschapv2_ident = response[0];
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_eap_init(struct eap_sm *sm,
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct eap_ttls_data *data,
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    EapType eap_type)
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->phase2_priv && data->phase2_method) {
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_method->reset(sm, data->phase2_priv);
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_method = NULL;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_priv = NULL;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							eap_type);
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data->phase2_method)
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->init_phase2 = 1;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2_priv = data->phase2_method->init(sm);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->init_phase2 = 0;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->phase2_priv == NULL ? -1 : 0;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 struct eap_ttls_data *data,
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 u8 *in_data, size_t in_len)
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 next_type = EAP_TYPE_NONE;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *hdr;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf buf;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *m = data->phase2_method;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *priv = data->phase2_priv;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL) {
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not "
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "initialized?!", __func__);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct eap_hdr *) in_data;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (u8 *) (hdr + 1);
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left = in_len - sizeof(*hdr);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; "
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "allowed types", pos + 1, left - 1);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_process_nak(sm, pos + 1, left - 1);
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[sm->user_eap_method_index].method !=
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    EAP_TYPE_NONE) {
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			next_type = sm->user->methods[
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user_eap_method_index++].method;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d",
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   next_type);
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to "
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "initialize EAP type %d",
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   next_type);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eap_ttls_state(data, FAILURE);
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_set(&buf, in_data, in_len);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->check(sm, priv, &buf)) {
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to "
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ignore the packet");
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->process(sm, priv, &buf);
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->method_pending == METHOD_PENDING_WAIT) {
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in "
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "pending wait state - save decrypted response");
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->pending_phase2_eap_resp);
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pending_phase2_eap_resp = wpabuf_dup(&buf);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!m->isDone(sm, priv))
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!m->isSuccess(sm, priv)) {
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed");
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->state) {
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_START:
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 "
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "Identity not found in the user "
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "database",
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sm->identity, sm->identity_len);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, PHASE2_METHOD);
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next_type = sm->user->methods[0].method;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user_eap_method_index = 1;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type);
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize "
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "EAP type %d", next_type);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
8851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case FAILURE:
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, data->state);
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap(struct eap_sm *sm,
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct eap_ttls_data *data,
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *eap, size_t eap_len)
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *hdr;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == PHASE2_START) {
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2");
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0)
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "initialize EAP-Identity");
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_len < sizeof(*hdr)) {
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP "
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "packet (len=%lu)", (unsigned long) eap_len);
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct eap_hdr *) eap;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = be_to_host16(hdr->length);
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "identifier=%d length=%lu", hdr->code, hdr->identifier,
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) len);
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > eap_len) {
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2"
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " EAP frame (hdr len=%lu, data len in AVP=%lu)",
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) eap_len);
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr,
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     len);
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in "
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Phase 2 EAP header", hdr->code);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2(struct eap_sm *sm,
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct eap_ttls_data *data,
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct wpabuf *in_buf)
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *in_decrypted;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_avp parse;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pending_phase2_eap_resp) {
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "- skip decryption and use old data");
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap(
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, data, wpabuf_head(data->pending_phase2_eap_resp),
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_len(data->pending_phase2_eap_resp));
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->pending_phase2_eap_resp);
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pending_phase2_eap_resp = NULL;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      in_buf);
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (in_decrypted == NULL) {
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data");
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    in_decrypted);
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(in_decrypted);
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parse.user_name) {
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm->identity);
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->identity = os_malloc(parse.user_name_len);
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->identity) {
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->identity, parse.user_name,
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  parse.user_name_len);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->identity_len = parse.user_name_len;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1)
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    != 0) {
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not "
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found in the user database");
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto done;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tnc_started && parse.eap == NULL) {
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP "
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "response from peer");
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parse.eap) {
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap(sm, data, parse.eap,
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    parse.eap_len);
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.user_password) {
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_pap(sm, data, parse.user_password,
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    parse.user_password_len);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.chap_password) {
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_chap(sm, data,
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_challenge,
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_challenge_len,
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_password,
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_password_len);
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.mschap_response) {
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_mschap(sm, data,
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_challenge,
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_challenge_len,
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_response,
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_response_len);
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.mschap2_response) {
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_mschapv2(sm, data,
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap_challenge,
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap_challenge_len,
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap2_response,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap2_response_len);
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(in_decrypted);
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(parse.eap);
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC");
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) {
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC");
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tnc_started = 1;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_ttls_state(data, PHASE2_METHOD);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_version(struct eap_sm *sm, void *priv,
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int peer_version)
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer_version < data->ttls_version) {
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "use version %d",
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   peer_version, data->ttls_version, peer_version);
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ttls_version = peer_version;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *respData)
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->state) {
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE1:
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_server_tls_phase1(sm, &data->ssl) < 0)
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_START:
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2(sm, data, data->ssl.tls_in);
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_start_tnc(sm, data);
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_MSCHAPV2_RESP:
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) ==
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0) {
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "acknowledged response");
10971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eap_ttls_state(data, SUCCESS);
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!data->mschapv2_resp_ok) {
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "acknowledged error");
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "frame from peer (payload len %lu, "
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "expected empty frame)",
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long)
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpabuf_len(data->ssl.tls_in));
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_start_tnc(sm, data);
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->state, __func__);
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process(struct eap_sm *sm, void *priv,
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf *respData)
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_tls_process(sm, &data->ssl, respData, data,
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   EAP_TYPE_TTLS, eap_ttls_process_version,
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   eap_ttls_process_msg) < 0)
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv)
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state == SUCCESS || data->state == FAILURE;
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *eapKeyData;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state != SUCCESS)
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       "ttls keying material",
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       EAP_TLS_KEY_LEN);
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapKeyData) {
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = EAP_TLS_KEY_LEN;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eapKeyData, EAP_TLS_KEY_LEN);
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eapKeyData;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv)
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state == SUCCESS;
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_ttls_register(void)
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method *eap;
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL)
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->init = eap_ttls_init;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->reset = eap_ttls_reset;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->buildReq = eap_ttls_buildReq;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->check = eap_ttls_check;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->process = eap_ttls_process;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isDone = eap_ttls_isDone;
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->getKey = eap_ttls_getKey;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isSuccess = eap_ttls_isSuccess;
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_server_method_register(eap);
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_server_method_free(eap);
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1192