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);
339c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	bin_clear_free(data, sizeof(*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=");
4126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!os_snprintf_error(end - pos, ret))
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 ||
512c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    os_memcmp_const(sm->user->password, user_password,
513c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt			    user_password_len) != 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
561c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN)
562c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    != 0 ||
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch");
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* MD5(Ident + Password + Challenge) */
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chap_md5(password[0], sm->user->password, sm->user->password_len,
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 challenge, challenge_len, hash);
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
575c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) ==
576c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    0) {
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password");
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschap(struct eap_sm *sm,
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   struct eap_ttls_data *data,
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *challenge, size_t challenge_len,
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *response, size_t response_len)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chal, nt_response[24];
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge == NULL || response == NULL ||
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN ||
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) {
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP "
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attributes (challenge len %lu response len %lu)",
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) challenge_len,
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) response_len);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password ||
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password "
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configured");
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chal = eap_ttls_implicit_challenge(sm, data,
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chal == NULL) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate "
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "challenge from TLS data");
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
621af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
622af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	eap_server_mschap_rx_callback(sm, "TTLS-MSCHAP",
623af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt				      sm->identity, sm->identity_len,
624af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt				      challenge, response + 2 + 24);
625af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
626af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
627c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN)
628c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    != 0 ||
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch");
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->password_hash)
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		challenge_response(challenge, sm->user->password, nt_response);
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nt_challenge_response(challenge, sm->user->password,
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      sm->user->password_len, nt_response);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
643c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(nt_response, response + 2 + 24, 24) == 0) {
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
6451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response");
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received",
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    response + 2 + 24, 24);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected",
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    nt_response, 24);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct eap_ttls_data *data,
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *challenge,
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t challenge_len,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *response, size_t response_len)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge,
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*auth_challenge;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t username_len, i;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge == NULL || response == NULL ||
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN ||
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) {
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 "
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attributes (challenge len %lu response len %lu)",
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) challenge_len,
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) response_len);
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->user || !sm->user->password ||
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password "
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configured");
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
68661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sm->identity == NULL) {
68761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user identity "
68861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   "known");
68961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		eap_ttls_state(data, FAILURE);
69061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
69161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
69261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* MSCHAPv2 does not include optional domain name in the
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * challenge-response calculation, so remove domain prefix
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (if present). */
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	username = sm->identity;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	username_len = sm->identity_len;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < username_len; i++) {
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (username[i] == '\\') {
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			username_len -= i + 1;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			username += i + 1;
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chal = eap_ttls_implicit_challenge(
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chal == NULL) {
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate "
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "challenge from TLS data");
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
715c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN)
716c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    != 0 ||
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) {
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(chal);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(chal);
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	auth_challenge = challenge;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer_challenge = response + 2;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User",
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  username, username_len);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge",
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge",
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->password_hash) {
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generate_nt_response_pwhash(auth_challenge, peer_challenge,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    username, username_len,
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sm->user->password,
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    nt_response);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generate_nt_response(auth_challenge, peer_challenge,
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     username, username_len,
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     sm->user->password,
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     sm->user->password_len,
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     nt_response);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
749af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
750af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	{
751af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		u8 challenge2[8];
752af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt
753af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		if (challenge_hash(peer_challenge, auth_challenge,
754af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt				   username, username_len, challenge2) == 0) {
755af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt			eap_server_mschap_rx_callback(sm, "TTLS-MSCHAPV2",
756af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt						      username, username_len,
757af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt						      challenge2, rx_resp);
758af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		}
759af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	}
760af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
761c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(nt_response, rx_resp, 24) == 0) {
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NT-Response");
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->mschapv2_resp_ok = 1;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user->password_hash) {
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			generate_authenticator_response_pwhash(
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user->password,
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				peer_challenge, auth_challenge,
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				username, username_len, nt_response,
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->mschapv2_auth_response);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			generate_authenticator_response(
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user->password, sm->user->password_len,
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				peer_challenge, auth_challenge,
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				username, username_len, nt_response,
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->mschapv2_auth_response);
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid "
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NT-Response");
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received",
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rx_resp, 24);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected",
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    nt_response, 24);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->mschapv2_resp_ok = 0;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_ttls_state(data, PHASE2_MSCHAPV2_RESP);
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->mschapv2_ident = response[0];
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_eap_init(struct eap_sm *sm,
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct eap_ttls_data *data,
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    EapType eap_type)
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->phase2_priv && data->phase2_method) {
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_method->reset(sm, data->phase2_priv);
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_method = NULL;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->phase2_priv = NULL;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							eap_type);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data->phase2_method)
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->init_phase2 = 1;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2_priv = data->phase2_method->init(sm);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->init_phase2 = 0;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->phase2_priv == NULL ? -1 : 0;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 struct eap_ttls_data *data,
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 u8 *in_data, size_t in_len)
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 next_type = EAP_TYPE_NONE;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *hdr;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf buf;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *m = data->phase2_method;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *priv = data->phase2_priv;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL) {
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not "
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "initialized?!", __func__);
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct eap_hdr *) in_data;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (u8 *) (hdr + 1);
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left = in_len - sizeof(*hdr);
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; "
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "allowed types", pos + 1, left - 1);
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_process_nak(sm, pos + 1, left - 1);
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[sm->user_eap_method_index].method !=
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    EAP_TYPE_NONE) {
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			next_type = sm->user->methods[
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user_eap_method_index++].method;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d",
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   next_type);
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to "
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "initialize EAP type %d",
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   next_type);
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eap_ttls_state(data, FAILURE);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_set(&buf, in_data, in_len);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->check(sm, priv, &buf)) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to "
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ignore the packet");
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->process(sm, priv, &buf);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->method_pending == METHOD_PENDING_WAIT) {
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in "
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "pending wait state - save decrypted response");
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->pending_phase2_eap_resp);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pending_phase2_eap_resp = wpabuf_dup(&buf);
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!m->isDone(sm, priv))
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!m->isSuccess(sm, priv)) {
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed");
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->state) {
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_START:
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 "
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "Identity not found in the user "
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "database",
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sm->identity, sm->identity_len);
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, PHASE2_METHOD);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next_type = sm->user->methods[0].method;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user_eap_method_index = 1;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type);
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_ttls_phase2_eap_init(sm, data, next_type)) {
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize "
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "EAP type %d", next_type);
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
9081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_ttls_state(data, SUCCESS);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case FAILURE:
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, data->state);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap(struct eap_sm *sm,
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct eap_ttls_data *data,
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *eap, size_t eap_len)
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *hdr;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == PHASE2_START) {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2");
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0)
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "initialize EAP-Identity");
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_len < sizeof(*hdr)) {
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP "
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "packet (len=%lu)", (unsigned long) eap_len);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct eap_hdr *) eap;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = be_to_host16(hdr->length);
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "identifier=%d length=%lu", hdr->code, hdr->identifier,
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) len);
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > eap_len) {
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2"
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " EAP frame (hdr len=%lu, data len in AVP=%lu)",
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) eap_len);
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr,
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     len);
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in "
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Phase 2 EAP header", hdr->code);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2(struct eap_sm *sm,
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct eap_ttls_data *data,
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct wpabuf *in_buf)
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *in_decrypted;
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_avp parse;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pending_phase2_eap_resp) {
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "- skip decryption and use old data");
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap(
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, data, wpabuf_head(data->pending_phase2_eap_resp),
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_len(data->pending_phase2_eap_resp));
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->pending_phase2_eap_resp);
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pending_phase2_eap_resp = NULL;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      in_buf);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (in_decrypted == NULL) {
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data");
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    in_decrypted);
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(in_decrypted);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parse.user_name) {
1009818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		char *nbuf;
1010b5d893b5dec601a58c3ce0fc9e5d6da3816ce97aDmitry Shmidt		nbuf = os_malloc(parse.user_name_len * 4 + 1);
1011818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (nbuf) {
1012b5d893b5dec601a58c3ce0fc9e5d6da3816ce97aDmitry Shmidt			printf_encode(nbuf, parse.user_name_len * 4 + 1,
1013818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				      parse.user_name,
1014818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				      parse.user_name_len);
1015818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			eap_log_msg(sm, "TTLS-User-Name '%s'", nbuf);
1016818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			os_free(nbuf);
1017818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
1018818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm->identity);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->identity = os_malloc(parse.user_name_len);
102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (sm->identity == NULL) {
102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			eap_ttls_state(data, FAILURE);
102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			goto done;
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(sm->identity, parse.user_name, parse.user_name_len);
102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sm->identity_len = parse.user_name_len;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1)
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    != 0) {
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not "
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found in the user database");
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto done;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tnc_started && parse.eap == NULL) {
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP "
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "response from peer");
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parse.eap) {
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_eap(sm, data, parse.eap,
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    parse.eap_len);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.user_password) {
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_pap(sm, data, parse.user_password,
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    parse.user_password_len);
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.chap_password) {
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_chap(sm, data,
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_challenge,
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_challenge_len,
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_password,
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     parse.chap_password_len);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.mschap_response) {
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_mschap(sm, data,
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_challenge,
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_challenge_len,
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_response,
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       parse.mschap_response_len);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (parse.mschap2_response) {
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2_mschapv2(sm, data,
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap_challenge,
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap_challenge_len,
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap2_response,
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 parse.mschap2_response_len);
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(in_decrypted);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(parse.eap);
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC");
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) {
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC");
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tnc_started = 1;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_ttls_state(data, PHASE2_METHOD);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_version(struct eap_sm *sm, void *priv,
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int peer_version)
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer_version < data->ttls_version) {
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "use version %d",
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   peer_version, data->ttls_version, peer_version);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->ttls_version = peer_version;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *respData)
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->state) {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE1:
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_server_tls_phase1(sm, &data->ssl) < 0)
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_START:
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_METHOD:
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_process_phase2(sm, data, data->ssl.tls_in);
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_start_tnc(sm, data);
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PHASE2_MSCHAPV2_RESP:
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) ==
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0) {
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "acknowledged response");
11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eap_ttls_state(data, SUCCESS);
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!data->mschapv2_resp_ok) {
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "acknowledged error");
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "frame from peer (payload len %lu, "
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "expected empty frame)",
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long)
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpabuf_len(data->ssl.tls_in));
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_ttls_state(data, FAILURE);
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_start_tnc(sm, data);
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->state, __func__);
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process(struct eap_sm *sm, void *priv,
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf *respData)
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_tls_process(sm, &data->ssl, respData, data,
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   EAP_TYPE_TTLS, eap_ttls_process_version,
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   eap_ttls_process_msg) < 0)
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_ttls_state(data, FAILURE);
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv)
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state == SUCCESS || data->state == FAILURE;
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *eapKeyData;
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state != SUCCESS)
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       "ttls keying material",
11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       EAP_TLS_KEY_LEN);
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapKeyData) {
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = EAP_TLS_KEY_LEN;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eapKeyData, EAP_TLS_KEY_LEN);
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eapKeyData;
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv)
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ttls_data *data = priv;
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state == SUCCESS;
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
12036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
12046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_ttls_data *data = priv;
12056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (data->state != SUCCESS)
12076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
12086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TTLS,
12106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt						len);
12116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
12126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
12156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
12166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_ttls_data *data = priv;
12176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 *eapKeyData, *emsk;
12186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (data->state != SUCCESS)
12206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
12216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
12236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					       "ttls keying material",
12246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
12256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (eapKeyData) {
12266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		emsk = os_malloc(EAP_EMSK_LEN);
12276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (emsk)
12286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
12296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  EAP_EMSK_LEN);
12306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
12316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else
12326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		emsk = NULL;
12336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (emsk) {
12356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		*len = EAP_EMSK_LEN;
12366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Derived EMSK",
12376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    emsk, EAP_EMSK_LEN);
12386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else {
12396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive EMSK");
12406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
12416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return emsk;
12436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
12446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_ttls_register(void)
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method *eap;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL)
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->init = eap_ttls_init;
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->reset = eap_ttls_reset;
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->buildReq = eap_ttls_buildReq;
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->check = eap_ttls_check;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->process = eap_ttls_process;
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isDone = eap_ttls_isDone;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->getKey = eap_ttls_getKey;
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isSuccess = eap_ttls_isSuccess;
12646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eap->getSessionId = eap_ttls_get_session_id;
12656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eap->get_emsk = eap_ttls_get_emsk;
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_server_method_register(eap);
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_server_method_free(eap);
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1272