18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-TLS (RFC 2716)
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, 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/tls.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_deinit(struct eap_sm *sm, void *priv);
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_tls_data {
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_ssl_data ssl;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *key_data;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_tls_init(struct eap_sm *sm)
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL ||
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ((sm->init_phase2 ? config->private_key2 : config->private_key)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     == NULL &&
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     (sm->init_phase2 ? config->engine2 : config->engine) == 0)) {
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_tls_deinit(sm, data);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->engine) {
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "PIN");
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sm_request_pin(sm);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ignore = TRUE;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (config->private_key && !config->private_key_passwd)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "key passphrase");
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sm_request_passphrase(sm);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ignore = TRUE;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_deinit(struct eap_sm *sm, void *priv)
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_peer_tls_ssl_deinit(sm, &data->ssl);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->key_data);
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tls_failure(struct eap_sm *sm,
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct eap_tls_data *data,
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct eap_method_ret *ret, int res,
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpabuf *resp, u8 id)
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret->methodState = METHOD_DONE;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret->decision = DECISION_FAIL;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == -1) {
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct eap_peer_config *config = eap_get_config(sm);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config) {
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * The TLS handshake failed. So better forget the old
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * PIN. It may be wrong, we cannot be sure but trying
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * the wrong one again might block it on the card--so
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * better ask the user again.
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(config->pin);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			config->pin = NULL;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp) {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This is likely an alert message, so send it instead of just
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * ACKing the error.
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return resp;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct eap_method_ret *ret)
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret->methodState = METHOD_DONE;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret->decision = DECISION_UNCOND_SUCC;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->key_data);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 "client EAP encryption",
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 EAP_TLS_KEY_LEN +
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 EAP_EMSK_LEN);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->key_data) {
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->key_data, EAP_TLS_KEY_LEN);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->key_data + EAP_TLS_KEY_LEN,
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				EAP_EMSK_LEN);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct eap_method_ret *ret,
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *reqData)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 flags, id;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret,
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					reqData, &left, &flags);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id = eap_get_id(reqData);
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & EAP_TLS_FLAGS_START) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-TLS: Start");
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left = 0; /* make sure that this frame is empty, even though it
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   * should always be, anyway */
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id,
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  pos, left, &resp);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_tls_failure(sm, data, ret, res, resp, id);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_tls_success(sm, data, ret);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 1) {
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(resp);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->key_data);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->key_data = NULL;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(data);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return priv;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf,
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      size_t buflen, int verbose)
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->key_data != NULL;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *key;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->key_data == NULL)
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key = os_malloc(EAP_TLS_KEY_LEN);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key == NULL)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = EAP_TLS_KEY_LEN;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return key;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_tls_data *data = priv;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *key;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->key_data == NULL)
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key = os_malloc(EAP_EMSK_LEN);
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key == NULL)
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = EAP_EMSK_LEN;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return key;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_register(void)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method *eap;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->init = eap_tls_init;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->deinit = eap_tls_deinit;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->process = eap_tls_process;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isKeyAvailable = eap_tls_isKeyAvailable;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->getKey = eap_tls_getKey;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->get_status = eap_tls_get_status;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->has_reauth_data = eap_tls_has_reauth_data;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->init_for_reauth = eap_tls_init_for_reauth;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->get_emsk = eap_tls_get_emsk;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_peer_method_register(eap);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_method_free(eap);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
284