xref: /dflybsd-src/contrib/wpa_supplicant/src/eap_server/eap_server_tls.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
13ff40c12SJohn Marino /*
23ff40c12SJohn Marino  * hostapd / EAP-TLS (RFC 2716)
33ff40c12SJohn Marino  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
73ff40c12SJohn Marino  */
83ff40c12SJohn Marino 
93ff40c12SJohn Marino #include "includes.h"
103ff40c12SJohn Marino 
113ff40c12SJohn Marino #include "common.h"
123ff40c12SJohn Marino #include "eap_i.h"
133ff40c12SJohn Marino #include "eap_tls_common.h"
143ff40c12SJohn Marino #include "crypto/tls.h"
153ff40c12SJohn Marino 
163ff40c12SJohn Marino 
173ff40c12SJohn Marino static void eap_tls_reset(struct eap_sm *sm, void *priv);
183ff40c12SJohn Marino 
193ff40c12SJohn Marino 
203ff40c12SJohn Marino struct eap_tls_data {
213ff40c12SJohn Marino 	struct eap_ssl_data ssl;
223ff40c12SJohn Marino 	enum { START, CONTINUE, SUCCESS, FAILURE } state;
233ff40c12SJohn Marino 	int established;
243ff40c12SJohn Marino 	u8 eap_type;
25*a1157835SDaniel Fojt 	int phase2;
263ff40c12SJohn Marino };
273ff40c12SJohn Marino 
283ff40c12SJohn Marino 
eap_tls_state_txt(int state)293ff40c12SJohn Marino static const char * eap_tls_state_txt(int state)
303ff40c12SJohn Marino {
313ff40c12SJohn Marino 	switch (state) {
323ff40c12SJohn Marino 	case START:
333ff40c12SJohn Marino 		return "START";
343ff40c12SJohn Marino 	case CONTINUE:
353ff40c12SJohn Marino 		return "CONTINUE";
363ff40c12SJohn Marino 	case SUCCESS:
373ff40c12SJohn Marino 		return "SUCCESS";
383ff40c12SJohn Marino 	case FAILURE:
393ff40c12SJohn Marino 		return "FAILURE";
403ff40c12SJohn Marino 	default:
413ff40c12SJohn Marino 		return "Unknown?!";
423ff40c12SJohn Marino 	}
433ff40c12SJohn Marino }
443ff40c12SJohn Marino 
453ff40c12SJohn Marino 
eap_tls_state(struct eap_tls_data * data,int state)463ff40c12SJohn Marino static void eap_tls_state(struct eap_tls_data *data, int state)
473ff40c12SJohn Marino {
483ff40c12SJohn Marino 	wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
493ff40c12SJohn Marino 		   eap_tls_state_txt(data->state),
503ff40c12SJohn Marino 		   eap_tls_state_txt(state));
513ff40c12SJohn Marino 	data->state = state;
52*a1157835SDaniel Fojt 	if (state == FAILURE)
53*a1157835SDaniel Fojt 		tls_connection_remove_session(data->ssl.conn);
54*a1157835SDaniel Fojt }
55*a1157835SDaniel Fojt 
56*a1157835SDaniel Fojt 
eap_tls_valid_session(struct eap_sm * sm,struct eap_tls_data * data)57*a1157835SDaniel Fojt static void eap_tls_valid_session(struct eap_sm *sm, struct eap_tls_data *data)
58*a1157835SDaniel Fojt {
59*a1157835SDaniel Fojt 	struct wpabuf *buf;
60*a1157835SDaniel Fojt 
61*a1157835SDaniel Fojt 	if (!sm->tls_session_lifetime)
62*a1157835SDaniel Fojt 		return;
63*a1157835SDaniel Fojt 
64*a1157835SDaniel Fojt 	buf = wpabuf_alloc(1);
65*a1157835SDaniel Fojt 	if (!buf)
66*a1157835SDaniel Fojt 		return;
67*a1157835SDaniel Fojt 	wpabuf_put_u8(buf, data->eap_type);
68*a1157835SDaniel Fojt 	tls_connection_set_success_data(data->ssl.conn, buf);
693ff40c12SJohn Marino }
703ff40c12SJohn Marino 
713ff40c12SJohn Marino 
eap_tls_init(struct eap_sm * sm)723ff40c12SJohn Marino static void * eap_tls_init(struct eap_sm *sm)
733ff40c12SJohn Marino {
743ff40c12SJohn Marino 	struct eap_tls_data *data;
753ff40c12SJohn Marino 
763ff40c12SJohn Marino 	data = os_zalloc(sizeof(*data));
773ff40c12SJohn Marino 	if (data == NULL)
783ff40c12SJohn Marino 		return NULL;
793ff40c12SJohn Marino 	data->state = START;
803ff40c12SJohn Marino 
81*a1157835SDaniel Fojt 	if (eap_server_tls_ssl_init(sm, &data->ssl, 1, EAP_TYPE_TLS)) {
823ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
833ff40c12SJohn Marino 		eap_tls_reset(sm, data);
843ff40c12SJohn Marino 		return NULL;
853ff40c12SJohn Marino 	}
863ff40c12SJohn Marino 
873ff40c12SJohn Marino 	data->eap_type = EAP_TYPE_TLS;
883ff40c12SJohn Marino 
89*a1157835SDaniel Fojt 	data->phase2 = sm->init_phase2;
90*a1157835SDaniel Fojt 
913ff40c12SJohn Marino 	return data;
923ff40c12SJohn Marino }
933ff40c12SJohn Marino 
943ff40c12SJohn Marino 
953ff40c12SJohn Marino #ifdef EAP_SERVER_UNAUTH_TLS
eap_unauth_tls_init(struct eap_sm * sm)963ff40c12SJohn Marino static void * eap_unauth_tls_init(struct eap_sm *sm)
973ff40c12SJohn Marino {
983ff40c12SJohn Marino 	struct eap_tls_data *data;
993ff40c12SJohn Marino 
1003ff40c12SJohn Marino 	data = os_zalloc(sizeof(*data));
1013ff40c12SJohn Marino 	if (data == NULL)
1023ff40c12SJohn Marino 		return NULL;
1033ff40c12SJohn Marino 	data->state = START;
1043ff40c12SJohn Marino 
105*a1157835SDaniel Fojt 	if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_UNAUTH_TLS_TYPE)) {
1063ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
1073ff40c12SJohn Marino 		eap_tls_reset(sm, data);
1083ff40c12SJohn Marino 		return NULL;
1093ff40c12SJohn Marino 	}
1103ff40c12SJohn Marino 
1113ff40c12SJohn Marino 	data->eap_type = EAP_UNAUTH_TLS_TYPE;
1123ff40c12SJohn Marino 	return data;
1133ff40c12SJohn Marino }
1143ff40c12SJohn Marino #endif /* EAP_SERVER_UNAUTH_TLS */
1153ff40c12SJohn Marino 
1163ff40c12SJohn Marino 
117*a1157835SDaniel Fojt #ifdef CONFIG_HS20
eap_wfa_unauth_tls_init(struct eap_sm * sm)118*a1157835SDaniel Fojt static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
119*a1157835SDaniel Fojt {
120*a1157835SDaniel Fojt 	struct eap_tls_data *data;
121*a1157835SDaniel Fojt 
122*a1157835SDaniel Fojt 	data = os_zalloc(sizeof(*data));
123*a1157835SDaniel Fojt 	if (data == NULL)
124*a1157835SDaniel Fojt 		return NULL;
125*a1157835SDaniel Fojt 	data->state = START;
126*a1157835SDaniel Fojt 
127*a1157835SDaniel Fojt 	if (eap_server_tls_ssl_init(sm, &data->ssl, 0,
128*a1157835SDaniel Fojt 				    EAP_WFA_UNAUTH_TLS_TYPE)) {
129*a1157835SDaniel Fojt 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
130*a1157835SDaniel Fojt 		eap_tls_reset(sm, data);
131*a1157835SDaniel Fojt 		return NULL;
132*a1157835SDaniel Fojt 	}
133*a1157835SDaniel Fojt 
134*a1157835SDaniel Fojt 	data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
135*a1157835SDaniel Fojt 	return data;
136*a1157835SDaniel Fojt }
137*a1157835SDaniel Fojt #endif /* CONFIG_HS20 */
138*a1157835SDaniel Fojt 
139*a1157835SDaniel Fojt 
eap_tls_reset(struct eap_sm * sm,void * priv)1403ff40c12SJohn Marino static void eap_tls_reset(struct eap_sm *sm, void *priv)
1413ff40c12SJohn Marino {
1423ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
1433ff40c12SJohn Marino 	if (data == NULL)
1443ff40c12SJohn Marino 		return;
1453ff40c12SJohn Marino 	eap_server_tls_ssl_deinit(sm, &data->ssl);
1463ff40c12SJohn Marino 	os_free(data);
1473ff40c12SJohn Marino }
1483ff40c12SJohn Marino 
1493ff40c12SJohn Marino 
eap_tls_build_start(struct eap_sm * sm,struct eap_tls_data * data,u8 id)1503ff40c12SJohn Marino static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
1513ff40c12SJohn Marino 					   struct eap_tls_data *data, u8 id)
1523ff40c12SJohn Marino {
1533ff40c12SJohn Marino 	struct wpabuf *req;
1543ff40c12SJohn Marino 
1553ff40c12SJohn Marino 	req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id);
1563ff40c12SJohn Marino 	if (req == NULL) {
1573ff40c12SJohn Marino 		wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
1583ff40c12SJohn Marino 			   "request");
1593ff40c12SJohn Marino 		eap_tls_state(data, FAILURE);
1603ff40c12SJohn Marino 		return NULL;
1613ff40c12SJohn Marino 	}
1623ff40c12SJohn Marino 
1633ff40c12SJohn Marino 	wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
1643ff40c12SJohn Marino 
1653ff40c12SJohn Marino 	eap_tls_state(data, CONTINUE);
1663ff40c12SJohn Marino 
1673ff40c12SJohn Marino 	return req;
1683ff40c12SJohn Marino }
1693ff40c12SJohn Marino 
1703ff40c12SJohn Marino 
eap_tls_buildReq(struct eap_sm * sm,void * priv,u8 id)1713ff40c12SJohn Marino static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
1723ff40c12SJohn Marino {
1733ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
1743ff40c12SJohn Marino 	struct wpabuf *res;
1753ff40c12SJohn Marino 
1763ff40c12SJohn Marino 	if (data->ssl.state == FRAG_ACK) {
1773ff40c12SJohn Marino 		return eap_server_tls_build_ack(id, data->eap_type, 0);
1783ff40c12SJohn Marino 	}
1793ff40c12SJohn Marino 
1803ff40c12SJohn Marino 	if (data->ssl.state == WAIT_FRAG_ACK) {
1813ff40c12SJohn Marino 		res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0,
1823ff40c12SJohn Marino 					       id);
1833ff40c12SJohn Marino 		goto check_established;
1843ff40c12SJohn Marino 	}
1853ff40c12SJohn Marino 
1863ff40c12SJohn Marino 	switch (data->state) {
1873ff40c12SJohn Marino 	case START:
1883ff40c12SJohn Marino 		return eap_tls_build_start(sm, data, id);
1893ff40c12SJohn Marino 	case CONTINUE:
1903ff40c12SJohn Marino 		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
1913ff40c12SJohn Marino 			data->established = 1;
1923ff40c12SJohn Marino 		break;
1933ff40c12SJohn Marino 	default:
1943ff40c12SJohn Marino 		wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
1953ff40c12SJohn Marino 			   __func__, data->state);
1963ff40c12SJohn Marino 		return NULL;
1973ff40c12SJohn Marino 	}
1983ff40c12SJohn Marino 
1993ff40c12SJohn Marino 	res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id);
2003ff40c12SJohn Marino 
2013ff40c12SJohn Marino check_established:
2023ff40c12SJohn Marino 	if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
2033ff40c12SJohn Marino 		/* TLS handshake has been completed and there are no more
2043ff40c12SJohn Marino 		 * fragments waiting to be sent out. */
2053ff40c12SJohn Marino 		wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
2063ff40c12SJohn Marino 		eap_tls_state(data, SUCCESS);
207*a1157835SDaniel Fojt 		eap_tls_valid_session(sm, data);
208*a1157835SDaniel Fojt 		if (sm->serial_num) {
209*a1157835SDaniel Fojt 			char user[128];
210*a1157835SDaniel Fojt 			int user_len;
211*a1157835SDaniel Fojt 
212*a1157835SDaniel Fojt 			user_len = os_snprintf(user, sizeof(user), "cert-%s",
213*a1157835SDaniel Fojt 					       sm->serial_num);
214*a1157835SDaniel Fojt 			if (eap_user_get(sm, (const u8 *) user, user_len,
215*a1157835SDaniel Fojt 					 data->phase2) < 0)
216*a1157835SDaniel Fojt 				wpa_printf(MSG_DEBUG,
217*a1157835SDaniel Fojt 					   "EAP-TLS: No user entry found based on the serial number of the client certificate ");
218*a1157835SDaniel Fojt 			else
219*a1157835SDaniel Fojt 				wpa_printf(MSG_DEBUG,
220*a1157835SDaniel Fojt 					   "EAP-TLS: Updated user entry based on the serial number of the client certificate ");
221*a1157835SDaniel Fojt 		}
2223ff40c12SJohn Marino 	}
2233ff40c12SJohn Marino 
2243ff40c12SJohn Marino 	return res;
2253ff40c12SJohn Marino }
2263ff40c12SJohn Marino 
2273ff40c12SJohn Marino 
eap_tls_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)2283ff40c12SJohn Marino static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
2293ff40c12SJohn Marino 			     struct wpabuf *respData)
2303ff40c12SJohn Marino {
2313ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
2323ff40c12SJohn Marino 	const u8 *pos;
2333ff40c12SJohn Marino 	size_t len;
2343ff40c12SJohn Marino 
2353ff40c12SJohn Marino 	if (data->eap_type == EAP_UNAUTH_TLS_TYPE)
2363ff40c12SJohn Marino 		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
2373ff40c12SJohn Marino 				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
2383ff40c12SJohn Marino 				       &len);
239*a1157835SDaniel Fojt 	else if (data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
240*a1157835SDaniel Fojt 		pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
241*a1157835SDaniel Fojt 				       EAP_VENDOR_WFA_UNAUTH_TLS, respData,
242*a1157835SDaniel Fojt 				       &len);
2433ff40c12SJohn Marino 	else
2443ff40c12SJohn Marino 		pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type,
2453ff40c12SJohn Marino 				       respData, &len);
2463ff40c12SJohn Marino 	if (pos == NULL || len < 1) {
2473ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
2483ff40c12SJohn Marino 		return TRUE;
2493ff40c12SJohn Marino 	}
2503ff40c12SJohn Marino 
2513ff40c12SJohn Marino 	return FALSE;
2523ff40c12SJohn Marino }
2533ff40c12SJohn Marino 
2543ff40c12SJohn Marino 
eap_tls_process_msg(struct eap_sm * sm,void * priv,const struct wpabuf * respData)2553ff40c12SJohn Marino static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
2563ff40c12SJohn Marino 				const struct wpabuf *respData)
2573ff40c12SJohn Marino {
2583ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
2593ff40c12SJohn Marino 	if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) {
2603ff40c12SJohn Marino 		wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
2613ff40c12SJohn Marino 			   "handshake message");
2623ff40c12SJohn Marino 		return;
2633ff40c12SJohn Marino 	}
264*a1157835SDaniel Fojt 	if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
2653ff40c12SJohn Marino 		eap_tls_state(data, FAILURE);
266*a1157835SDaniel Fojt 		return;
267*a1157835SDaniel Fojt 	}
268*a1157835SDaniel Fojt 
269*a1157835SDaniel Fojt 	if (data->ssl.tls_v13 &&
270*a1157835SDaniel Fojt 	    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
271*a1157835SDaniel Fojt 		struct wpabuf *plain, *encr;
272*a1157835SDaniel Fojt 
273*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
274*a1157835SDaniel Fojt 			   "EAP-TLS: Send empty application data to indicate end of exchange");
275*a1157835SDaniel Fojt 		/* FIX: This should be an empty application data based on
276*a1157835SDaniel Fojt 		 * draft-ietf-emu-eap-tls13-05, but OpenSSL does not allow zero
277*a1157835SDaniel Fojt 		 * length payload (SSL_write() documentation explicitly
278*a1157835SDaniel Fojt 		 * describes this as not allowed), so work around that for now
279*a1157835SDaniel Fojt 		 * by sending out a payload of one octet. Hopefully the draft
280*a1157835SDaniel Fojt 		 * specification will change to allow this so that no crypto
281*a1157835SDaniel Fojt 		 * library changes are needed. */
282*a1157835SDaniel Fojt 		plain = wpabuf_alloc(1);
283*a1157835SDaniel Fojt 		if (!plain)
284*a1157835SDaniel Fojt 			return;
285*a1157835SDaniel Fojt 		wpabuf_put_u8(plain, 0);
286*a1157835SDaniel Fojt 		encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
287*a1157835SDaniel Fojt 		wpabuf_free(plain);
288*a1157835SDaniel Fojt 		if (!encr)
289*a1157835SDaniel Fojt 			return;
290*a1157835SDaniel Fojt 		if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) {
291*a1157835SDaniel Fojt 			wpa_printf(MSG_INFO,
292*a1157835SDaniel Fojt 				   "EAP-TLS: Failed to resize output buffer");
293*a1157835SDaniel Fojt 			wpabuf_free(encr);
294*a1157835SDaniel Fojt 			return;
295*a1157835SDaniel Fojt 		}
296*a1157835SDaniel Fojt 		wpabuf_put_buf(data->ssl.tls_out, encr);
297*a1157835SDaniel Fojt 		wpa_hexdump_buf(MSG_DEBUG,
298*a1157835SDaniel Fojt 				"EAP-TLS: Data appended to the message", encr);
299*a1157835SDaniel Fojt 		wpabuf_free(encr);
300*a1157835SDaniel Fojt 	}
3013ff40c12SJohn Marino }
3023ff40c12SJohn Marino 
3033ff40c12SJohn Marino 
eap_tls_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)3043ff40c12SJohn Marino static void eap_tls_process(struct eap_sm *sm, void *priv,
3053ff40c12SJohn Marino 			    struct wpabuf *respData)
3063ff40c12SJohn Marino {
3073ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
308*a1157835SDaniel Fojt 	const struct wpabuf *buf;
309*a1157835SDaniel Fojt 	const u8 *pos;
310*a1157835SDaniel Fojt 
3113ff40c12SJohn Marino 	if (eap_server_tls_process(sm, &data->ssl, respData, data,
3123ff40c12SJohn Marino 				   data->eap_type, NULL, eap_tls_process_msg) <
313*a1157835SDaniel Fojt 	    0) {
3143ff40c12SJohn Marino 		eap_tls_state(data, FAILURE);
315*a1157835SDaniel Fojt 		return;
316*a1157835SDaniel Fojt 	}
317*a1157835SDaniel Fojt 
318*a1157835SDaniel Fojt 	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
319*a1157835SDaniel Fojt 	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
320*a1157835SDaniel Fojt 		return;
321*a1157835SDaniel Fojt 
322*a1157835SDaniel Fojt 	buf = tls_connection_get_success_data(data->ssl.conn);
323*a1157835SDaniel Fojt 	if (!buf || wpabuf_len(buf) < 1) {
324*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
325*a1157835SDaniel Fojt 			   "EAP-TLS: No success data in resumed session - reject attempt");
326*a1157835SDaniel Fojt 		eap_tls_state(data, FAILURE);
327*a1157835SDaniel Fojt 		return;
328*a1157835SDaniel Fojt 	}
329*a1157835SDaniel Fojt 
330*a1157835SDaniel Fojt 	pos = wpabuf_head(buf);
331*a1157835SDaniel Fojt 	if (*pos != data->eap_type) {
332*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
333*a1157835SDaniel Fojt 			   "EAP-TLS: Resumed session for another EAP type (%u) - reject attempt",
334*a1157835SDaniel Fojt 			   *pos);
335*a1157835SDaniel Fojt 		eap_tls_state(data, FAILURE);
336*a1157835SDaniel Fojt 		return;
337*a1157835SDaniel Fojt 	}
338*a1157835SDaniel Fojt 
339*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG,
340*a1157835SDaniel Fojt 		   "EAP-TLS: Resuming previous session");
341*a1157835SDaniel Fojt 	eap_tls_state(data, SUCCESS);
342*a1157835SDaniel Fojt 	tls_connection_set_success_data_resumed(data->ssl.conn);
343*a1157835SDaniel Fojt 	/* TODO: Cache serial number with session and update EAP user
344*a1157835SDaniel Fojt 	 * information based on the cached serial number */
3453ff40c12SJohn Marino }
3463ff40c12SJohn Marino 
3473ff40c12SJohn Marino 
eap_tls_isDone(struct eap_sm * sm,void * priv)3483ff40c12SJohn Marino static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
3493ff40c12SJohn Marino {
3503ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
3513ff40c12SJohn Marino 	return data->state == SUCCESS || data->state == FAILURE;
3523ff40c12SJohn Marino }
3533ff40c12SJohn Marino 
3543ff40c12SJohn Marino 
eap_tls_getKey(struct eap_sm * sm,void * priv,size_t * len)3553ff40c12SJohn Marino static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
3563ff40c12SJohn Marino {
3573ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
3583ff40c12SJohn Marino 	u8 *eapKeyData;
359*a1157835SDaniel Fojt 	const char *label;
360*a1157835SDaniel Fojt 	const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
361*a1157835SDaniel Fojt 	const u8 *context = NULL;
362*a1157835SDaniel Fojt 	size_t context_len = 0;
3633ff40c12SJohn Marino 
3643ff40c12SJohn Marino 	if (data->state != SUCCESS)
3653ff40c12SJohn Marino 		return NULL;
3663ff40c12SJohn Marino 
367*a1157835SDaniel Fojt 	if (data->ssl.tls_v13) {
368*a1157835SDaniel Fojt 		label = "EXPORTER_EAP_TLS_Key_Material";
369*a1157835SDaniel Fojt 		context = eap_tls13_context;
370*a1157835SDaniel Fojt 		context_len = 1;
371*a1157835SDaniel Fojt 	} else {
372*a1157835SDaniel Fojt 		label = "client EAP encryption";
373*a1157835SDaniel Fojt 	}
374*a1157835SDaniel Fojt 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
375*a1157835SDaniel Fojt 					       context, context_len,
376*a1157835SDaniel Fojt 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
3773ff40c12SJohn Marino 	if (eapKeyData) {
3783ff40c12SJohn Marino 		*len = EAP_TLS_KEY_LEN;
3793ff40c12SJohn Marino 		wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
3803ff40c12SJohn Marino 			    eapKeyData, EAP_TLS_KEY_LEN);
381*a1157835SDaniel Fojt 		os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
3823ff40c12SJohn Marino 	} else {
3833ff40c12SJohn Marino 		wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
3843ff40c12SJohn Marino 	}
3853ff40c12SJohn Marino 
3863ff40c12SJohn Marino 	return eapKeyData;
3873ff40c12SJohn Marino }
3883ff40c12SJohn Marino 
3893ff40c12SJohn Marino 
eap_tls_get_emsk(struct eap_sm * sm,void * priv,size_t * len)3903ff40c12SJohn Marino static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
3913ff40c12SJohn Marino {
3923ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
3933ff40c12SJohn Marino 	u8 *eapKeyData, *emsk;
394*a1157835SDaniel Fojt 	const char *label;
395*a1157835SDaniel Fojt 	const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
396*a1157835SDaniel Fojt 	const u8 *context = NULL;
397*a1157835SDaniel Fojt 	size_t context_len = 0;
3983ff40c12SJohn Marino 
3993ff40c12SJohn Marino 	if (data->state != SUCCESS)
4003ff40c12SJohn Marino 		return NULL;
4013ff40c12SJohn Marino 
402*a1157835SDaniel Fojt 	if (data->ssl.tls_v13) {
403*a1157835SDaniel Fojt 		label = "EXPORTER_EAP_TLS_Key_Material";
404*a1157835SDaniel Fojt 		context = eap_tls13_context;
405*a1157835SDaniel Fojt 		context_len = 1;
406*a1157835SDaniel Fojt 	} else {
407*a1157835SDaniel Fojt 		label = "client EAP encryption";
408*a1157835SDaniel Fojt 	}
409*a1157835SDaniel Fojt 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
410*a1157835SDaniel Fojt 					       context, context_len,
4113ff40c12SJohn Marino 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
4123ff40c12SJohn Marino 	if (eapKeyData) {
4133ff40c12SJohn Marino 		emsk = os_malloc(EAP_EMSK_LEN);
4143ff40c12SJohn Marino 		if (emsk)
4153ff40c12SJohn Marino 			os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
4163ff40c12SJohn Marino 				  EAP_EMSK_LEN);
417*a1157835SDaniel Fojt 		bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
4183ff40c12SJohn Marino 	} else
4193ff40c12SJohn Marino 		emsk = NULL;
4203ff40c12SJohn Marino 
4213ff40c12SJohn Marino 	if (emsk) {
4223ff40c12SJohn Marino 		*len = EAP_EMSK_LEN;
4233ff40c12SJohn Marino 		wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
4243ff40c12SJohn Marino 			    emsk, EAP_EMSK_LEN);
4253ff40c12SJohn Marino 	} else {
4263ff40c12SJohn Marino 		wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
4273ff40c12SJohn Marino 	}
4283ff40c12SJohn Marino 
4293ff40c12SJohn Marino 	return emsk;
4303ff40c12SJohn Marino }
4313ff40c12SJohn Marino 
4323ff40c12SJohn Marino 
eap_tls_isSuccess(struct eap_sm * sm,void * priv)4333ff40c12SJohn Marino static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
4343ff40c12SJohn Marino {
4353ff40c12SJohn Marino 	struct eap_tls_data *data = priv;
4363ff40c12SJohn Marino 	return data->state == SUCCESS;
4373ff40c12SJohn Marino }
4383ff40c12SJohn Marino 
4393ff40c12SJohn Marino 
eap_tls_get_session_id(struct eap_sm * sm,void * priv,size_t * len)440*a1157835SDaniel Fojt static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
441*a1157835SDaniel Fojt {
442*a1157835SDaniel Fojt 	struct eap_tls_data *data = priv;
443*a1157835SDaniel Fojt 
444*a1157835SDaniel Fojt 	if (data->state != SUCCESS)
445*a1157835SDaniel Fojt 		return NULL;
446*a1157835SDaniel Fojt 
447*a1157835SDaniel Fojt 	return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TLS,
448*a1157835SDaniel Fojt 						len);
449*a1157835SDaniel Fojt }
450*a1157835SDaniel Fojt 
451*a1157835SDaniel Fojt 
eap_server_tls_register(void)4523ff40c12SJohn Marino int eap_server_tls_register(void)
4533ff40c12SJohn Marino {
4543ff40c12SJohn Marino 	struct eap_method *eap;
4553ff40c12SJohn Marino 
4563ff40c12SJohn Marino 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
4573ff40c12SJohn Marino 				      EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
4583ff40c12SJohn Marino 	if (eap == NULL)
4593ff40c12SJohn Marino 		return -1;
4603ff40c12SJohn Marino 
4613ff40c12SJohn Marino 	eap->init = eap_tls_init;
4623ff40c12SJohn Marino 	eap->reset = eap_tls_reset;
4633ff40c12SJohn Marino 	eap->buildReq = eap_tls_buildReq;
4643ff40c12SJohn Marino 	eap->check = eap_tls_check;
4653ff40c12SJohn Marino 	eap->process = eap_tls_process;
4663ff40c12SJohn Marino 	eap->isDone = eap_tls_isDone;
4673ff40c12SJohn Marino 	eap->getKey = eap_tls_getKey;
4683ff40c12SJohn Marino 	eap->isSuccess = eap_tls_isSuccess;
4693ff40c12SJohn Marino 	eap->get_emsk = eap_tls_get_emsk;
470*a1157835SDaniel Fojt 	eap->getSessionId = eap_tls_get_session_id;
4713ff40c12SJohn Marino 
472*a1157835SDaniel Fojt 	return eap_server_method_register(eap);
4733ff40c12SJohn Marino }
4743ff40c12SJohn Marino 
4753ff40c12SJohn Marino 
4763ff40c12SJohn Marino #ifdef EAP_SERVER_UNAUTH_TLS
eap_server_unauth_tls_register(void)4773ff40c12SJohn Marino int eap_server_unauth_tls_register(void)
4783ff40c12SJohn Marino {
4793ff40c12SJohn Marino 	struct eap_method *eap;
4803ff40c12SJohn Marino 
4813ff40c12SJohn Marino 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
4823ff40c12SJohn Marino 				      EAP_VENDOR_UNAUTH_TLS,
4833ff40c12SJohn Marino 				      EAP_VENDOR_TYPE_UNAUTH_TLS,
4843ff40c12SJohn Marino 				      "UNAUTH-TLS");
4853ff40c12SJohn Marino 	if (eap == NULL)
4863ff40c12SJohn Marino 		return -1;
4873ff40c12SJohn Marino 
4883ff40c12SJohn Marino 	eap->init = eap_unauth_tls_init;
4893ff40c12SJohn Marino 	eap->reset = eap_tls_reset;
4903ff40c12SJohn Marino 	eap->buildReq = eap_tls_buildReq;
4913ff40c12SJohn Marino 	eap->check = eap_tls_check;
4923ff40c12SJohn Marino 	eap->process = eap_tls_process;
4933ff40c12SJohn Marino 	eap->isDone = eap_tls_isDone;
4943ff40c12SJohn Marino 	eap->getKey = eap_tls_getKey;
4953ff40c12SJohn Marino 	eap->isSuccess = eap_tls_isSuccess;
4963ff40c12SJohn Marino 	eap->get_emsk = eap_tls_get_emsk;
4973ff40c12SJohn Marino 
498*a1157835SDaniel Fojt 	return eap_server_method_register(eap);
4993ff40c12SJohn Marino }
5003ff40c12SJohn Marino #endif /* EAP_SERVER_UNAUTH_TLS */
501*a1157835SDaniel Fojt 
502*a1157835SDaniel Fojt 
503*a1157835SDaniel Fojt #ifdef CONFIG_HS20
eap_server_wfa_unauth_tls_register(void)504*a1157835SDaniel Fojt int eap_server_wfa_unauth_tls_register(void)
505*a1157835SDaniel Fojt {
506*a1157835SDaniel Fojt 	struct eap_method *eap;
507*a1157835SDaniel Fojt 
508*a1157835SDaniel Fojt 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
509*a1157835SDaniel Fojt 				      EAP_VENDOR_WFA_NEW,
510*a1157835SDaniel Fojt 				      EAP_VENDOR_WFA_UNAUTH_TLS,
511*a1157835SDaniel Fojt 				      "WFA-UNAUTH-TLS");
512*a1157835SDaniel Fojt 	if (eap == NULL)
513*a1157835SDaniel Fojt 		return -1;
514*a1157835SDaniel Fojt 
515*a1157835SDaniel Fojt 	eap->init = eap_wfa_unauth_tls_init;
516*a1157835SDaniel Fojt 	eap->reset = eap_tls_reset;
517*a1157835SDaniel Fojt 	eap->buildReq = eap_tls_buildReq;
518*a1157835SDaniel Fojt 	eap->check = eap_tls_check;
519*a1157835SDaniel Fojt 	eap->process = eap_tls_process;
520*a1157835SDaniel Fojt 	eap->isDone = eap_tls_isDone;
521*a1157835SDaniel Fojt 	eap->getKey = eap_tls_getKey;
522*a1157835SDaniel Fojt 	eap->isSuccess = eap_tls_isSuccess;
523*a1157835SDaniel Fojt 	eap->get_emsk = eap_tls_get_emsk;
524*a1157835SDaniel Fojt 
525*a1157835SDaniel Fojt 	return eap_server_method_register(eap);
526*a1157835SDaniel Fojt }
527*a1157835SDaniel Fojt #endif /* CONFIG_HS20 */
528