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