xref: /freebsd/contrib/wpa/src/eap_peer/eap_tls.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
2*a90b9d01SCy Schubert  * EAP peer method: EAP-TLS (RFC 5216, RFC 9190)
3c1d255d3SCy Schubert  * Copyright (c) 2004-2008, 2012-2019, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/tls.h"
1339beb93cSSam Leffler #include "eap_i.h"
1439beb93cSSam Leffler #include "eap_tls_common.h"
1539beb93cSSam Leffler #include "eap_config.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler 
1839beb93cSSam Leffler static void eap_tls_deinit(struct eap_sm *sm, void *priv);
1939beb93cSSam Leffler 
2039beb93cSSam Leffler 
2139beb93cSSam Leffler struct eap_tls_data {
2239beb93cSSam Leffler 	struct eap_ssl_data ssl;
2339beb93cSSam Leffler 	u8 *key_data;
245b9c547cSRui Paulo 	u8 *session_id;
255b9c547cSRui Paulo 	size_t id_len;
26f05cddf9SRui Paulo 	void *ssl_ctx;
27f05cddf9SRui Paulo 	u8 eap_type;
28780fb4a2SCy Schubert 	struct wpabuf *pending_resp;
29*a90b9d01SCy Schubert 	bool prot_success_received;
3039beb93cSSam Leffler };
3139beb93cSSam Leffler 
3239beb93cSSam Leffler 
eap_tls_init(struct eap_sm * sm)3339beb93cSSam Leffler static void * eap_tls_init(struct eap_sm *sm)
3439beb93cSSam Leffler {
3539beb93cSSam Leffler 	struct eap_tls_data *data;
3639beb93cSSam Leffler 	struct eap_peer_config *config = eap_get_config(sm);
37c1d255d3SCy Schubert 	struct eap_peer_cert_config *cert;
38c1d255d3SCy Schubert 
39c1d255d3SCy Schubert 	if (!config)
40c1d255d3SCy Schubert 		return NULL;
41c1d255d3SCy Schubert 	if (!sm->init_phase2)
42c1d255d3SCy Schubert 		cert = &config->cert;
43c1d255d3SCy Schubert 	else if (sm->use_machine_cred)
44c1d255d3SCy Schubert 		cert = &config->machine_cert;
45c1d255d3SCy Schubert 	else
46c1d255d3SCy Schubert 		cert = &config->phase2_cert;
47c1d255d3SCy Schubert 	if (!cert->private_key && cert->engine == 0) {
4839beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
4939beb93cSSam Leffler 		return NULL;
5039beb93cSSam Leffler 	}
5139beb93cSSam Leffler 
5239beb93cSSam Leffler 	data = os_zalloc(sizeof(*data));
5339beb93cSSam Leffler 	if (data == NULL)
5439beb93cSSam Leffler 		return NULL;
5539beb93cSSam Leffler 
56f05cddf9SRui Paulo 	data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
57f05cddf9SRui Paulo 		sm->ssl_ctx;
58f05cddf9SRui Paulo 
59f05cddf9SRui Paulo 	if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) {
6039beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
6139beb93cSSam Leffler 		eap_tls_deinit(sm, data);
62c1d255d3SCy Schubert 		if (cert->engine) {
6339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
6439beb93cSSam Leffler 				   "PIN");
6539beb93cSSam Leffler 			eap_sm_request_pin(sm);
66c1d255d3SCy Schubert 			sm->ignore = true;
67c1d255d3SCy Schubert 		} else if (cert->private_key && !cert->private_key_passwd) {
6839beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
6939beb93cSSam Leffler 				   "key passphrase");
7039beb93cSSam Leffler 			eap_sm_request_passphrase(sm);
71c1d255d3SCy Schubert 			sm->ignore = true;
7239beb93cSSam Leffler 		}
7339beb93cSSam Leffler 		return NULL;
7439beb93cSSam Leffler 	}
7539beb93cSSam Leffler 
76f05cddf9SRui Paulo 	data->eap_type = EAP_TYPE_TLS;
77f05cddf9SRui Paulo 
7839beb93cSSam Leffler 	return data;
7939beb93cSSam Leffler }
8039beb93cSSam Leffler 
8139beb93cSSam Leffler 
82f05cddf9SRui Paulo #ifdef EAP_UNAUTH_TLS
eap_unauth_tls_init(struct eap_sm * sm)83f05cddf9SRui Paulo static void * eap_unauth_tls_init(struct eap_sm *sm)
84f05cddf9SRui Paulo {
85f05cddf9SRui Paulo 	struct eap_tls_data *data;
86f05cddf9SRui Paulo 	struct eap_peer_config *config = eap_get_config(sm);
87f05cddf9SRui Paulo 
88f05cddf9SRui Paulo 	data = os_zalloc(sizeof(*data));
89f05cddf9SRui Paulo 	if (data == NULL)
90f05cddf9SRui Paulo 		return NULL;
91f05cddf9SRui Paulo 
92f05cddf9SRui Paulo 	data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
93f05cddf9SRui Paulo 		sm->ssl_ctx;
94f05cddf9SRui Paulo 
95f05cddf9SRui Paulo 	if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
96f05cddf9SRui Paulo 				  EAP_UNAUTH_TLS_TYPE)) {
97f05cddf9SRui Paulo 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
98f05cddf9SRui Paulo 		eap_tls_deinit(sm, data);
99f05cddf9SRui Paulo 		return NULL;
100f05cddf9SRui Paulo 	}
101f05cddf9SRui Paulo 
102f05cddf9SRui Paulo 	data->eap_type = EAP_UNAUTH_TLS_TYPE;
103f05cddf9SRui Paulo 
104f05cddf9SRui Paulo 	return data;
105f05cddf9SRui Paulo }
106f05cddf9SRui Paulo #endif /* EAP_UNAUTH_TLS */
107f05cddf9SRui Paulo 
108f05cddf9SRui Paulo 
1095b9c547cSRui Paulo #ifdef CONFIG_HS20
eap_wfa_unauth_tls_init(struct eap_sm * sm)1105b9c547cSRui Paulo static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
1115b9c547cSRui Paulo {
1125b9c547cSRui Paulo 	struct eap_tls_data *data;
1135b9c547cSRui Paulo 	struct eap_peer_config *config = eap_get_config(sm);
1145b9c547cSRui Paulo 
1155b9c547cSRui Paulo 	data = os_zalloc(sizeof(*data));
1165b9c547cSRui Paulo 	if (data == NULL)
1175b9c547cSRui Paulo 		return NULL;
1185b9c547cSRui Paulo 
1195b9c547cSRui Paulo 	data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
1205b9c547cSRui Paulo 		sm->ssl_ctx;
1215b9c547cSRui Paulo 
1225b9c547cSRui Paulo 	if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
1235b9c547cSRui Paulo 				  EAP_WFA_UNAUTH_TLS_TYPE)) {
1245b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
1255b9c547cSRui Paulo 		eap_tls_deinit(sm, data);
1265b9c547cSRui Paulo 		return NULL;
1275b9c547cSRui Paulo 	}
1285b9c547cSRui Paulo 
1295b9c547cSRui Paulo 	data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
1305b9c547cSRui Paulo 
1315b9c547cSRui Paulo 	return data;
1325b9c547cSRui Paulo }
1335b9c547cSRui Paulo #endif /* CONFIG_HS20 */
1345b9c547cSRui Paulo 
1355b9c547cSRui Paulo 
eap_tls_free_key(struct eap_tls_data * data)1365b9c547cSRui Paulo static void eap_tls_free_key(struct eap_tls_data *data)
1375b9c547cSRui Paulo {
1385b9c547cSRui Paulo 	if (data->key_data) {
1395b9c547cSRui Paulo 		bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1405b9c547cSRui Paulo 		data->key_data = NULL;
1415b9c547cSRui Paulo 	}
1425b9c547cSRui Paulo }
1435b9c547cSRui Paulo 
1445b9c547cSRui Paulo 
eap_tls_deinit(struct eap_sm * sm,void * priv)14539beb93cSSam Leffler static void eap_tls_deinit(struct eap_sm *sm, void *priv)
14639beb93cSSam Leffler {
14739beb93cSSam Leffler 	struct eap_tls_data *data = priv;
14839beb93cSSam Leffler 	if (data == NULL)
14939beb93cSSam Leffler 		return;
15039beb93cSSam Leffler 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
1515b9c547cSRui Paulo 	eap_tls_free_key(data);
1525b9c547cSRui Paulo 	os_free(data->session_id);
153780fb4a2SCy Schubert 	wpabuf_free(data->pending_resp);
15439beb93cSSam Leffler 	os_free(data);
15539beb93cSSam Leffler }
15639beb93cSSam Leffler 
15739beb93cSSam Leffler 
eap_tls_failure(struct eap_sm * sm,struct eap_tls_data * data,struct eap_method_ret * ret,int res,struct wpabuf * resp,u8 id)15839beb93cSSam Leffler static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
15939beb93cSSam Leffler 				       struct eap_tls_data *data,
16039beb93cSSam Leffler 				       struct eap_method_ret *ret, int res,
16139beb93cSSam Leffler 				       struct wpabuf *resp, u8 id)
16239beb93cSSam Leffler {
16339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
16439beb93cSSam Leffler 
16539beb93cSSam Leffler 	ret->methodState = METHOD_DONE;
16639beb93cSSam Leffler 	ret->decision = DECISION_FAIL;
16739beb93cSSam Leffler 
16839beb93cSSam Leffler 	if (resp) {
16939beb93cSSam Leffler 		/*
17039beb93cSSam Leffler 		 * This is likely an alert message, so send it instead of just
17139beb93cSSam Leffler 		 * ACKing the error.
17239beb93cSSam Leffler 		 */
17339beb93cSSam Leffler 		return resp;
17439beb93cSSam Leffler 	}
17539beb93cSSam Leffler 
176f05cddf9SRui Paulo 	return eap_peer_tls_build_ack(id, data->eap_type, 0);
17739beb93cSSam Leffler }
17839beb93cSSam Leffler 
17939beb93cSSam Leffler 
eap_tls_success(struct eap_sm * sm,struct eap_tls_data * data,struct eap_method_ret * ret)18039beb93cSSam Leffler static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
18139beb93cSSam Leffler 			    struct eap_method_ret *ret)
18239beb93cSSam Leffler {
18385732ac8SCy Schubert 	const char *label;
184206b73d0SCy Schubert 	const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
185206b73d0SCy Schubert 	const u8 *context = NULL;
186206b73d0SCy Schubert 	size_t context_len = 0;
18785732ac8SCy Schubert 
18839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
18939beb93cSSam Leffler 
19085732ac8SCy Schubert 	if (data->ssl.tls_out) {
19185732ac8SCy Schubert 		wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining");
19285732ac8SCy Schubert 		return;
19385732ac8SCy Schubert 	}
19485732ac8SCy Schubert 
19585732ac8SCy Schubert 	if (data->ssl.tls_v13) {
19685732ac8SCy Schubert 		label = "EXPORTER_EAP_TLS_Key_Material";
197206b73d0SCy Schubert 		context = eap_tls13_context;
198206b73d0SCy Schubert 		context_len = 1;
19985732ac8SCy Schubert 
20085732ac8SCy Schubert 		/* A possible NewSessionTicket may be received before
20185732ac8SCy Schubert 		 * EAP-Success, so need to allow it to be received. */
20285732ac8SCy Schubert 		ret->methodState = METHOD_MAY_CONT;
20385732ac8SCy Schubert 		ret->decision = DECISION_COND_SUCC;
20485732ac8SCy Schubert 	} else {
20585732ac8SCy Schubert 		label = "client EAP encryption";
20685732ac8SCy Schubert 
20739beb93cSSam Leffler 		ret->methodState = METHOD_DONE;
20839beb93cSSam Leffler 		ret->decision = DECISION_UNCOND_SUCC;
20985732ac8SCy Schubert 	}
21039beb93cSSam Leffler 
2115b9c547cSRui Paulo 	eap_tls_free_key(data);
21285732ac8SCy Schubert 	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
213206b73d0SCy Schubert 						 context, context_len,
21439beb93cSSam Leffler 						 EAP_TLS_KEY_LEN +
21539beb93cSSam Leffler 						 EAP_EMSK_LEN);
21639beb93cSSam Leffler 	if (data->key_data) {
21739beb93cSSam Leffler 		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
21839beb93cSSam Leffler 				data->key_data, EAP_TLS_KEY_LEN);
21939beb93cSSam Leffler 		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
22039beb93cSSam Leffler 				data->key_data + EAP_TLS_KEY_LEN,
22139beb93cSSam Leffler 				EAP_EMSK_LEN);
22239beb93cSSam Leffler 	} else {
22339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
22439beb93cSSam Leffler 	}
2255b9c547cSRui Paulo 
2265b9c547cSRui Paulo 	os_free(data->session_id);
2275b9c547cSRui Paulo 	data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
2285b9c547cSRui Paulo 							  EAP_TYPE_TLS,
2295b9c547cSRui Paulo 			                                  &data->id_len);
2305b9c547cSRui Paulo 	if (data->session_id) {
2315b9c547cSRui Paulo 		wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id",
2325b9c547cSRui Paulo 			    data->session_id, data->id_len);
2335b9c547cSRui Paulo 	} else {
2345b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id");
2355b9c547cSRui Paulo 	}
23639beb93cSSam Leffler }
23739beb93cSSam Leffler 
23839beb93cSSam Leffler 
eap_tls_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)23939beb93cSSam Leffler static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
24039beb93cSSam Leffler 				       struct eap_method_ret *ret,
24139beb93cSSam Leffler 				       const struct wpabuf *reqData)
24239beb93cSSam Leffler {
24339beb93cSSam Leffler 	size_t left;
24439beb93cSSam Leffler 	int res;
24539beb93cSSam Leffler 	struct wpabuf *resp;
24639beb93cSSam Leffler 	u8 flags, id;
24739beb93cSSam Leffler 	const u8 *pos;
24839beb93cSSam Leffler 	struct eap_tls_data *data = priv;
249325151a3SRui Paulo 	struct wpabuf msg;
25039beb93cSSam Leffler 
251780fb4a2SCy Schubert 	if (sm->waiting_ext_cert_check && data->pending_resp) {
252780fb4a2SCy Schubert 		struct eap_peer_config *config = eap_get_config(sm);
253780fb4a2SCy Schubert 
254780fb4a2SCy Schubert 		if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
255780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
256780fb4a2SCy Schubert 				   "EAP-TLS: External certificate check succeeded - continue handshake");
257780fb4a2SCy Schubert 			resp = data->pending_resp;
258780fb4a2SCy Schubert 			data->pending_resp = NULL;
259780fb4a2SCy Schubert 			sm->waiting_ext_cert_check = 0;
260780fb4a2SCy Schubert 			return resp;
261780fb4a2SCy Schubert 		}
262780fb4a2SCy Schubert 
263780fb4a2SCy Schubert 		if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
264780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
265780fb4a2SCy Schubert 				   "EAP-TLS: External certificate check failed - force authentication failure");
266780fb4a2SCy Schubert 			ret->methodState = METHOD_DONE;
267780fb4a2SCy Schubert 			ret->decision = DECISION_FAIL;
268780fb4a2SCy Schubert 			sm->waiting_ext_cert_check = 0;
269780fb4a2SCy Schubert 			return NULL;
270780fb4a2SCy Schubert 		}
271780fb4a2SCy Schubert 
272780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
273780fb4a2SCy Schubert 			   "EAP-TLS: Continuing to wait external server certificate validation");
274780fb4a2SCy Schubert 		return NULL;
275780fb4a2SCy Schubert 	}
276780fb4a2SCy Schubert 
277f05cddf9SRui Paulo 	pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
27839beb93cSSam Leffler 					reqData, &left, &flags);
27939beb93cSSam Leffler 	if (pos == NULL)
28039beb93cSSam Leffler 		return NULL;
28139beb93cSSam Leffler 	id = eap_get_id(reqData);
28239beb93cSSam Leffler 
28339beb93cSSam Leffler 	if (flags & EAP_TLS_FLAGS_START) {
28439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "EAP-TLS: Start");
28539beb93cSSam Leffler 		left = 0; /* make sure that this frame is empty, even though it
28639beb93cSSam Leffler 			   * should always be, anyway */
28739beb93cSSam Leffler 	}
28839beb93cSSam Leffler 
28939beb93cSSam Leffler 	resp = NULL;
290325151a3SRui Paulo 	wpabuf_set(&msg, pos, left);
291f05cddf9SRui Paulo 	res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0,
292325151a3SRui Paulo 					  id, &msg, &resp);
29339beb93cSSam Leffler 
29439beb93cSSam Leffler 	if (res < 0) {
29539beb93cSSam Leffler 		return eap_tls_failure(sm, data, ret, res, resp, id);
29639beb93cSSam Leffler 	}
29739beb93cSSam Leffler 
298780fb4a2SCy Schubert 	if (sm->waiting_ext_cert_check) {
299780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
300780fb4a2SCy Schubert 			   "EAP-TLS: Waiting external server certificate validation");
301780fb4a2SCy Schubert 		wpabuf_free(data->pending_resp);
302780fb4a2SCy Schubert 		data->pending_resp = resp;
303780fb4a2SCy Schubert 		return NULL;
304780fb4a2SCy Schubert 	}
305780fb4a2SCy Schubert 
306*a90b9d01SCy Schubert 	/* RFC 9190 Section 2.5 */
307c1d255d3SCy Schubert 	if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 &&
308c1d255d3SCy Schubert 	    *wpabuf_head_u8(resp) == 0) {
309*a90b9d01SCy Schubert 		wpa_printf(MSG_DEBUG,
310*a90b9d01SCy Schubert 			   "EAP-TLS: ACKing protected success indication (appl data 0x00)");
311206b73d0SCy Schubert 		eap_peer_tls_reset_output(&data->ssl);
312206b73d0SCy Schubert 		res = 1;
313*a90b9d01SCy Schubert 		ret->methodState = METHOD_DONE;
314*a90b9d01SCy Schubert 		ret->decision = DECISION_UNCOND_SUCC;
315*a90b9d01SCy Schubert 		data->prot_success_received = true;
316206b73d0SCy Schubert 	}
317206b73d0SCy Schubert 
318*a90b9d01SCy Schubert 	if (tls_connection_established(data->ssl_ctx, data->ssl.conn) &&
319*a90b9d01SCy Schubert 	    (!data->ssl.tls_v13 || data->prot_success_received))
32039beb93cSSam Leffler 		eap_tls_success(sm, data, ret);
32139beb93cSSam Leffler 
32239beb93cSSam Leffler 	if (res == 1) {
32339beb93cSSam Leffler 		wpabuf_free(resp);
324f05cddf9SRui Paulo 		return eap_peer_tls_build_ack(id, data->eap_type, 0);
32539beb93cSSam Leffler 	}
32639beb93cSSam Leffler 
32739beb93cSSam Leffler 	return resp;
32839beb93cSSam Leffler }
32939beb93cSSam Leffler 
33039beb93cSSam Leffler 
eap_tls_has_reauth_data(struct eap_sm * sm,void * priv)331c1d255d3SCy Schubert static bool eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
33239beb93cSSam Leffler {
33339beb93cSSam Leffler 	struct eap_tls_data *data = priv;
334f05cddf9SRui Paulo 	return tls_connection_established(data->ssl_ctx, data->ssl.conn);
33539beb93cSSam Leffler }
33639beb93cSSam Leffler 
33739beb93cSSam Leffler 
eap_tls_deinit_for_reauth(struct eap_sm * sm,void * priv)33839beb93cSSam Leffler static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
33939beb93cSSam Leffler {
340780fb4a2SCy Schubert 	struct eap_tls_data *data = priv;
341780fb4a2SCy Schubert 
342780fb4a2SCy Schubert 	wpabuf_free(data->pending_resp);
343780fb4a2SCy Schubert 	data->pending_resp = NULL;
344*a90b9d01SCy Schubert 	data->prot_success_received = false;
34539beb93cSSam Leffler }
34639beb93cSSam Leffler 
34739beb93cSSam Leffler 
eap_tls_init_for_reauth(struct eap_sm * sm,void * priv)34839beb93cSSam Leffler static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
34939beb93cSSam Leffler {
35039beb93cSSam Leffler 	struct eap_tls_data *data = priv;
3515b9c547cSRui Paulo 	eap_tls_free_key(data);
3525b9c547cSRui Paulo 	os_free(data->session_id);
3535b9c547cSRui Paulo 	data->session_id = NULL;
35439beb93cSSam Leffler 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
35539beb93cSSam Leffler 		os_free(data);
35639beb93cSSam Leffler 		return NULL;
35739beb93cSSam Leffler 	}
35839beb93cSSam Leffler 	return priv;
35939beb93cSSam Leffler }
36039beb93cSSam Leffler 
36139beb93cSSam Leffler 
eap_tls_get_status(struct eap_sm * sm,void * priv,char * buf,size_t buflen,int verbose)36239beb93cSSam Leffler static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf,
36339beb93cSSam Leffler 			      size_t buflen, int verbose)
36439beb93cSSam Leffler {
36539beb93cSSam Leffler 	struct eap_tls_data *data = priv;
36639beb93cSSam Leffler 	return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
36739beb93cSSam Leffler }
36839beb93cSSam Leffler 
36939beb93cSSam Leffler 
eap_tls_isKeyAvailable(struct eap_sm * sm,void * priv)370c1d255d3SCy Schubert static bool eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv)
37139beb93cSSam Leffler {
37239beb93cSSam Leffler 	struct eap_tls_data *data = priv;
37339beb93cSSam Leffler 	return data->key_data != NULL;
37439beb93cSSam Leffler }
37539beb93cSSam Leffler 
37639beb93cSSam Leffler 
eap_tls_getKey(struct eap_sm * sm,void * priv,size_t * len)37739beb93cSSam Leffler static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
37839beb93cSSam Leffler {
37939beb93cSSam Leffler 	struct eap_tls_data *data = priv;
38039beb93cSSam Leffler 	u8 *key;
38139beb93cSSam Leffler 
38239beb93cSSam Leffler 	if (data->key_data == NULL)
38339beb93cSSam Leffler 		return NULL;
38439beb93cSSam Leffler 
38585732ac8SCy Schubert 	key = os_memdup(data->key_data, EAP_TLS_KEY_LEN);
38639beb93cSSam Leffler 	if (key == NULL)
38739beb93cSSam Leffler 		return NULL;
38839beb93cSSam Leffler 
38939beb93cSSam Leffler 	*len = EAP_TLS_KEY_LEN;
39039beb93cSSam Leffler 
39139beb93cSSam Leffler 	return key;
39239beb93cSSam Leffler }
39339beb93cSSam Leffler 
39439beb93cSSam Leffler 
eap_tls_get_emsk(struct eap_sm * sm,void * priv,size_t * len)39539beb93cSSam Leffler static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
39639beb93cSSam Leffler {
39739beb93cSSam Leffler 	struct eap_tls_data *data = priv;
39839beb93cSSam Leffler 	u8 *key;
39939beb93cSSam Leffler 
40039beb93cSSam Leffler 	if (data->key_data == NULL)
40139beb93cSSam Leffler 		return NULL;
40239beb93cSSam Leffler 
40385732ac8SCy Schubert 	key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
40439beb93cSSam Leffler 	if (key == NULL)
40539beb93cSSam Leffler 		return NULL;
40639beb93cSSam Leffler 
40739beb93cSSam Leffler 	*len = EAP_EMSK_LEN;
40839beb93cSSam Leffler 
40939beb93cSSam Leffler 	return key;
41039beb93cSSam Leffler }
41139beb93cSSam Leffler 
41239beb93cSSam Leffler 
eap_tls_get_session_id(struct eap_sm * sm,void * priv,size_t * len)4135b9c547cSRui Paulo static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
4145b9c547cSRui Paulo {
4155b9c547cSRui Paulo 	struct eap_tls_data *data = priv;
4165b9c547cSRui Paulo 	u8 *id;
4175b9c547cSRui Paulo 
4185b9c547cSRui Paulo 	if (data->session_id == NULL)
4195b9c547cSRui Paulo 		return NULL;
4205b9c547cSRui Paulo 
42185732ac8SCy Schubert 	id = os_memdup(data->session_id, data->id_len);
4225b9c547cSRui Paulo 	if (id == NULL)
4235b9c547cSRui Paulo 		return NULL;
4245b9c547cSRui Paulo 
4255b9c547cSRui Paulo 	*len = data->id_len;
4265b9c547cSRui Paulo 
4275b9c547cSRui Paulo 	return id;
4285b9c547cSRui Paulo }
4295b9c547cSRui Paulo 
4305b9c547cSRui Paulo 
eap_peer_tls_register(void)43139beb93cSSam Leffler int eap_peer_tls_register(void)
43239beb93cSSam Leffler {
43339beb93cSSam Leffler 	struct eap_method *eap;
43439beb93cSSam Leffler 
43539beb93cSSam Leffler 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
43639beb93cSSam Leffler 				    EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
43739beb93cSSam Leffler 	if (eap == NULL)
43839beb93cSSam Leffler 		return -1;
43939beb93cSSam Leffler 
44039beb93cSSam Leffler 	eap->init = eap_tls_init;
44139beb93cSSam Leffler 	eap->deinit = eap_tls_deinit;
44239beb93cSSam Leffler 	eap->process = eap_tls_process;
44339beb93cSSam Leffler 	eap->isKeyAvailable = eap_tls_isKeyAvailable;
44439beb93cSSam Leffler 	eap->getKey = eap_tls_getKey;
4455b9c547cSRui Paulo 	eap->getSessionId = eap_tls_get_session_id;
44639beb93cSSam Leffler 	eap->get_status = eap_tls_get_status;
44739beb93cSSam Leffler 	eap->has_reauth_data = eap_tls_has_reauth_data;
44839beb93cSSam Leffler 	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
44939beb93cSSam Leffler 	eap->init_for_reauth = eap_tls_init_for_reauth;
45039beb93cSSam Leffler 	eap->get_emsk = eap_tls_get_emsk;
45139beb93cSSam Leffler 
452780fb4a2SCy Schubert 	return eap_peer_method_register(eap);
45339beb93cSSam Leffler }
454f05cddf9SRui Paulo 
455f05cddf9SRui Paulo 
456f05cddf9SRui Paulo #ifdef EAP_UNAUTH_TLS
eap_peer_unauth_tls_register(void)457f05cddf9SRui Paulo int eap_peer_unauth_tls_register(void)
458f05cddf9SRui Paulo {
459f05cddf9SRui Paulo 	struct eap_method *eap;
460f05cddf9SRui Paulo 
461f05cddf9SRui Paulo 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
462f05cddf9SRui Paulo 				    EAP_VENDOR_UNAUTH_TLS,
463f05cddf9SRui Paulo 				    EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS");
464f05cddf9SRui Paulo 	if (eap == NULL)
465f05cddf9SRui Paulo 		return -1;
466f05cddf9SRui Paulo 
467f05cddf9SRui Paulo 	eap->init = eap_unauth_tls_init;
468f05cddf9SRui Paulo 	eap->deinit = eap_tls_deinit;
469f05cddf9SRui Paulo 	eap->process = eap_tls_process;
470f05cddf9SRui Paulo 	eap->isKeyAvailable = eap_tls_isKeyAvailable;
471f05cddf9SRui Paulo 	eap->getKey = eap_tls_getKey;
472f05cddf9SRui Paulo 	eap->get_status = eap_tls_get_status;
473f05cddf9SRui Paulo 	eap->has_reauth_data = eap_tls_has_reauth_data;
474f05cddf9SRui Paulo 	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
475f05cddf9SRui Paulo 	eap->init_for_reauth = eap_tls_init_for_reauth;
476f05cddf9SRui Paulo 	eap->get_emsk = eap_tls_get_emsk;
477f05cddf9SRui Paulo 
478780fb4a2SCy Schubert 	return eap_peer_method_register(eap);
479f05cddf9SRui Paulo }
480f05cddf9SRui Paulo #endif /* EAP_UNAUTH_TLS */
4815b9c547cSRui Paulo 
4825b9c547cSRui Paulo 
4835b9c547cSRui Paulo #ifdef CONFIG_HS20
eap_peer_wfa_unauth_tls_register(void)4845b9c547cSRui Paulo int eap_peer_wfa_unauth_tls_register(void)
4855b9c547cSRui Paulo {
4865b9c547cSRui Paulo 	struct eap_method *eap;
4875b9c547cSRui Paulo 
4885b9c547cSRui Paulo 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
4895b9c547cSRui Paulo 				    EAP_VENDOR_WFA_NEW,
4905b9c547cSRui Paulo 				    EAP_VENDOR_WFA_UNAUTH_TLS,
4915b9c547cSRui Paulo 				    "WFA-UNAUTH-TLS");
4925b9c547cSRui Paulo 	if (eap == NULL)
4935b9c547cSRui Paulo 		return -1;
4945b9c547cSRui Paulo 
4955b9c547cSRui Paulo 	eap->init = eap_wfa_unauth_tls_init;
4965b9c547cSRui Paulo 	eap->deinit = eap_tls_deinit;
4975b9c547cSRui Paulo 	eap->process = eap_tls_process;
4985b9c547cSRui Paulo 	eap->isKeyAvailable = eap_tls_isKeyAvailable;
4995b9c547cSRui Paulo 	eap->getKey = eap_tls_getKey;
5005b9c547cSRui Paulo 	eap->get_status = eap_tls_get_status;
5015b9c547cSRui Paulo 	eap->has_reauth_data = eap_tls_has_reauth_data;
5025b9c547cSRui Paulo 	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
5035b9c547cSRui Paulo 	eap->init_for_reauth = eap_tls_init_for_reauth;
5045b9c547cSRui Paulo 	eap->get_emsk = eap_tls_get_emsk;
5055b9c547cSRui Paulo 
506780fb4a2SCy Schubert 	return eap_peer_method_register(eap);
5075b9c547cSRui Paulo }
5085b9c547cSRui Paulo #endif /* CONFIG_HS20 */
509