18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-TLS/PEAP/TTLS/FAST server common functions
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, 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/sha1.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  u8 code, u8 identifier)
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (type == EAP_UNAUTH_TLS_TYPE)
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     code, identifier);
28f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
29f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
30f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				     EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
31f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				     code, identifier);
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			     identifier);
3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
37818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TLS_INTERNAL
38818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidtstatic void eap_server_tls_log_cb(void *ctx, const char *msg)
39818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt{
40818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	struct eap_sm *sm = ctx;
41818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	eap_log_msg(sm, "TLS: %s", msg);
42818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt}
43818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TLS_INTERNAL */
44818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
45818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    int verify_peer)
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4901904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	if (sm->ssl_ctx == NULL) {
5001904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
5101904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		return -1;
5201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	}
5301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->eap = sm;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2 = sm->init_phase2;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->conn = tls_connection_init(sm->ssl_ctx);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->conn == NULL) {
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "connection");
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
64818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TLS_INTERNAL
65818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
66818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
67818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
68818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
69818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TLS_INTERNAL */
70818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "of TLS peer certificate");
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_connection_deinit(sm->ssl_ctx, data->conn);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->conn = NULL;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->phase2) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Limit the fragment size in the inner TLS authentication
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * since the outer authentication with EAP-PEAP does not yet
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * support fragmentation */
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_out_limit > 100)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->tls_out_limit -= 100;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_connection_deinit(sm->ssl_ctx, data->conn);
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_tls_free_in_buf(data);
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(data->tls_out);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out = NULL;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       char *label, size_t len)
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_keys keys;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rnd = NULL, *out;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = os_malloc(len);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out == NULL)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0)
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return out;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keys.client_random == NULL || keys.server_random == NULL ||
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    keys.master_key == NULL)
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rnd == NULL)
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(rnd, keys.client_random, keys.client_random_len);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(rnd + keys.client_random_len, keys.server_random,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  keys.server_random_len);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			     label, rnd, keys.client_random_len +
1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			     keys.server_random_len, out, len))
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rnd);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(out);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rnd);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 int eap_type, int version, u8 id)
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t send_len, plen;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out == NULL) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = version;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (1 + send_len > data->tls_out_limit) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		send_len = data->tls_out_limit - 1;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_out_pos == 0) {
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			send_len -= 4;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = 1 + send_len;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		plen += 4;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(req, flags); /* Flags */
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be32(req, wpabuf_len(data->tls_out));
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			send_len);
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out_pos += send_len;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(message sent completely)",
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) send_len);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_out);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_out = NULL;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_out_pos = 0;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = MSG;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(%lu more to send)", (unsigned long) send_len,
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_len(data->tls_out) -
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->tls_out_pos);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = WAIT_FRAG_ACK;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(req, version); /* Flags */
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_process_cont(struct eap_ssl_data *data,
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *buf, size_t len)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Process continuation of a pending message */
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > wpabuf_tailroom(data->tls_in)) {
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(data->tls_in, buf, len);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "bytes more", (unsigned long) len,
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) wpabuf_tailroom(data->tls_in));
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_process_fragment(struct eap_ssl_data *data,
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 flags, u32 message_length,
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *buf, size_t len)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Process a fragment that is not the last one of the message */
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fragmented packet");
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL) {
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* First fragment of the message */
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Limit length to avoid rogue peers from causing large
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * memory allocations. */
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (message_length > 65536) {
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " over 64 kB)");
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
256d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (len > message_length) {
257d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
258d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "first fragment of frame (TLS Message "
259d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "Length %d bytes)",
260d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   (int) len, (int) message_length);
261d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
262d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
263d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_in = wpabuf_alloc(message_length);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_in == NULL) {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(data->tls_in, buf, len);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fragment, waiting for %lu bytes more",
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len,
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_tailroom(data->tls_in));
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out) {
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* This should not happen.. */
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "processing new message");
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_out);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_ASSERT(data->tls_out == NULL);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							data->conn,
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							data->tls_in, NULL);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out == NULL) {
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TLS processing has failed - return error */
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "report error");
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 **pos, size_t *left)
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int tls_msg_len = 0;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = *pos + *left;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*left < 4) {
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length");
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_msg_len = WPA_GET_BE32(*pos);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   tls_msg_len);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos += 4;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*left -= 4;
325d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
326d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (*left > tls_msg_len) {
327d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
328d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "bytes) smaller than this fragment (%d "
329d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "bytes)", (int) tls_msg_len, (int) *left);
330d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
331d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "Message Length %u", flags, tls_msg_len);
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == WAIT_FRAG_ACK) {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*left != 0) {
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "WAIT_FRAG_ACK state");
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in &&
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    *pos, end - *pos) < 0)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = FRAG_ACK;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == FRAG_ACK) {
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: All fragments received");
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = MSG;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL) {
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Wrap unfragmented messages as wpabuf without extra copy */
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_in = &data->tmpbuf;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in != &data->tmpbuf)
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_in);
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_in = NULL;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct eap_ssl_data *data,
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *plain)
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     plain);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   struct wpabuf *respData, void *priv, int eap_type,
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int (*proc_version)(struct eap_sm *sm, void *priv,
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       int peer_version),
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   void (*proc_msg)(struct eap_sm *sm, void *priv,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const struct wpabuf *respData))
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret, res = 0;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (eap_type == EAP_UNAUTH_TLS_TYPE)
41361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
41461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
41561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       &left);
416f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
417f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
418f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				       EAP_VENDOR_WFA_UNAUTH_TLS, respData,
419f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				       &left);
42061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
42161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
42261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       &left);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL || left < 1)
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Should not happen - frame already validated */
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = *pos++;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left--;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) wpabuf_len(respData), flags);
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (proc_version &&
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0) {
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret == 1)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (proc_msg)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		proc_msg(sm, priv, respData);
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "TLS processing");
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_tls_free_in_buf(data);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
455