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,
47d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			    int verify_peer, int eap_type)
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 session_ctx[8];
50d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int flags = 0;
51d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	if (sm->ssl_ctx == NULL) {
5301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
5401904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		return -1;
5501904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	}
5601904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->eap = sm;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->phase2 = sm->init_phase2;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->conn = tls_connection_init(sm->ssl_ctx);
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->conn == NULL) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "connection");
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
67818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TLS_INTERNAL
68818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
69818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
70818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
71818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
72818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TLS_INTERNAL */
73818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
74d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (eap_type != EAP_TYPE_FAST)
75d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		flags |= TLS_CONN_DISABLE_SESSION_TICKET;
76d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(session_ctx, "hostapd", 7);
77d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	session_ctx[7] = (u8) eap_type;
78d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer,
79d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      flags, session_ctx,
80d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      sizeof(session_ctx))) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "of TLS peer certificate");
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_connection_deinit(sm->ssl_ctx, data->conn);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->conn = NULL;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->phase2) {
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Limit the fragment size in the inner TLS authentication
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * since the outer authentication with EAP-PEAP does not yet
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * support fragmentation */
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_out_limit > 100)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->tls_out_limit -= 100;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_connection_deinit(sm->ssl_ctx, data->conn);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_tls_free_in_buf(data);
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(data->tls_out);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out = NULL;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       char *label, size_t len)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
112af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	u8 *out;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = os_malloc(len);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out == NULL)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, 0,
119af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt			       out, len)) {
120af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		os_free(out);
121af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt		return NULL;
122af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	}
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/**
1296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
1306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @data: Data for TLS processing
1326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
1336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @len: Pointer to length of the session ID generated
1346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: Pointer to allocated Session-Id on success or %NULL on failure
1356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt *
1366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This function derive the Session-Id based on the TLS session data
1376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * (client/server random and method type).
1386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt *
1396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * The caller is responsible for freeing the returned buffer.
1406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */
1416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtu8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
1426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      struct eap_ssl_data *data, u8 eap_type,
1436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      size_t *len)
1446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
145d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct tls_random keys;
1466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 *out;
1476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
148d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (keys.client_random == NULL || keys.server_random == NULL)
1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*len = 1 + keys.client_random_len + keys.server_random_len;
1556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	out = os_malloc(*len);
1566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (out == NULL)
1576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Session-Id = EAP type || client.random || server.random */
1606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	out[0] = eap_type;
1616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(out + 1, keys.client_random, keys.client_random_len);
1626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
1636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		  keys.server_random_len);
1646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return out;
1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 int eap_type, int version, u8 id)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t send_len, plen;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out == NULL) {
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = version;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (1 + send_len > data->tls_out_limit) {
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		send_len = data->tls_out_limit - 1;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_out_pos == 0) {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			send_len -= 4;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = 1 + send_len;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		plen += 4;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(req, flags); /* Flags */
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be32(req, wpabuf_len(data->tls_out));
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			send_len);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out_pos += send_len;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(message sent completely)",
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) send_len);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_out);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_out = NULL;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_out_pos = 0;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = MSG;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(%lu more to send)", (unsigned long) send_len,
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_len(data->tls_out) -
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->tls_out_pos);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = WAIT_FRAG_ACK;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(req, version); /* Flags */
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_process_cont(struct eap_ssl_data *data,
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *buf, size_t len)
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Process continuation of a pending message */
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > wpabuf_tailroom(data->tls_in)) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(data->tls_in, buf, len);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "bytes more", (unsigned long) len,
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) wpabuf_tailroom(data->tls_in));
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_process_fragment(struct eap_ssl_data *data,
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 flags, u32 message_length,
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *buf, size_t len)
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Process a fragment that is not the last one of the message */
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fragmented packet");
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL) {
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* First fragment of the message */
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Limit length to avoid rogue peers from causing large
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * memory allocations. */
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (message_length > 65536) {
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " over 64 kB)");
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
282d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (len > message_length) {
283d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
284d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "first fragment of frame (TLS Message "
285d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "Length %d bytes)",
286d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   (int) len, (int) message_length);
287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_in = wpabuf_alloc(message_length);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tls_in == NULL) {
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(data->tls_in, buf, len);
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fragment, waiting for %lu bytes more",
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len,
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_tailroom(data->tls_in));
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* This should not happen.. */
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "processing new message");
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_out);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_ASSERT(data->tls_out == NULL);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							data->conn,
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							data->tls_in, NULL);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_out == NULL) {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TLS processing has failed - return error */
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "report error");
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 **pos, size_t *left)
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int tls_msg_len = 0;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = *pos + *left;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*left < 4) {
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length");
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_msg_len = WPA_GET_BE32(*pos);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   tls_msg_len);
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos += 4;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*left -= 4;
351d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
352d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (*left > tls_msg_len) {
353d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
354d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "bytes) smaller than this fragment (%d "
355d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "bytes)", (int) tls_msg_len, (int) *left);
356d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
357d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "Message Length %u", flags, tls_msg_len);
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == WAIT_FRAG_ACK) {
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*left != 0) {
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "WAIT_FRAG_ACK state");
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in &&
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    *pos, end - *pos) < 0)
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = FRAG_ACK;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->state == FRAG_ACK) {
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "SSL: All fragments received");
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = MSG;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in == NULL) {
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Wrap unfragmented messages as wpabuf without extra copy */
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->tls_in = &data->tmpbuf;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->tls_in != &data->tmpbuf)
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(data->tls_in);
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->tls_in = NULL;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct eap_ssl_data *data,
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *plain)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     plain);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   struct wpabuf *respData, void *priv, int eap_type,
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int (*proc_version)(struct eap_sm *sm, void *priv,
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       int peer_version),
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   void (*proc_msg)(struct eap_sm *sm, void *priv,
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const struct wpabuf *respData))
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret, res = 0;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (eap_type == EAP_UNAUTH_TLS_TYPE)
43961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
44061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
44161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       &left);
442f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
443f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
444f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				       EAP_VENDOR_WFA_UNAUTH_TLS, respData,
445f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				       &left);
44661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
44761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
44861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       &left);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL || left < 1)
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Should not happen - frame already validated */
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = *pos++;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left--;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) wpabuf_len(respData), flags);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (proc_version &&
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0) {
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret == 1)
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (proc_msg)
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		proc_msg(sm, priv, respData);
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "TLS processing");
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_tls_free_in_buf(data);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
481