2 * hostapd / EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "eap_tls_common.h"
23 static void eap_tls_reset(struct eap_sm *sm, void *priv);
27 struct eap_ssl_data ssl;
28 enum { START, CONTINUE, SUCCESS, FAILURE } state;
32 static const char * eap_tls_state_txt(int state)
49 static void eap_tls_state(struct eap_tls_data *data, int state)
51 wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
52 eap_tls_state_txt(data->state),
53 eap_tls_state_txt(state));
58 static void * eap_tls_init(struct eap_sm *sm)
60 struct eap_tls_data *data;
62 data = os_zalloc(sizeof(*data));
67 if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) {
68 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
69 eap_tls_reset(sm, data);
77 static void eap_tls_reset(struct eap_sm *sm, void *priv)
79 struct eap_tls_data *data = priv;
82 eap_server_tls_ssl_deinit(sm, &data->ssl);
87 static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
88 struct eap_tls_data *data, u8 id)
92 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST,
95 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
97 eap_tls_state(data, FAILURE);
101 wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
103 eap_tls_state(data, CONTINUE);
109 static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
111 struct eap_tls_data *data = priv;
114 if (data->ssl.state == FRAG_ACK) {
115 return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0);
118 if (data->ssl.state == WAIT_FRAG_ACK) {
119 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0,
123 switch (data->state) {
125 return eap_tls_build_start(sm, data, id);
127 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
128 wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
129 eap_tls_state(data, SUCCESS);
133 wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
134 __func__, data->state);
138 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id);
142 static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
143 struct wpabuf *respData)
148 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len);
149 if (pos == NULL || len < 1) {
150 wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
158 static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
159 const struct wpabuf *respData)
161 struct eap_tls_data *data = priv;
162 if (eap_server_tls_phase1(sm, &data->ssl) < 0)
163 eap_tls_state(data, FAILURE);
167 static void eap_tls_process(struct eap_sm *sm, void *priv,
168 struct wpabuf *respData)
170 struct eap_tls_data *data = priv;
171 if (eap_server_tls_process(sm, &data->ssl, respData, data,
172 EAP_TYPE_TLS, NULL, eap_tls_process_msg) <
174 eap_tls_state(data, FAILURE);
178 static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
180 struct eap_tls_data *data = priv;
181 return data->state == SUCCESS || data->state == FAILURE;
185 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
187 struct eap_tls_data *data = priv;
190 if (data->state != SUCCESS)
193 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
194 "client EAP encryption",
197 *len = EAP_TLS_KEY_LEN;
198 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
199 eapKeyData, EAP_TLS_KEY_LEN);
201 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
208 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
210 struct eap_tls_data *data = priv;
211 u8 *eapKeyData, *emsk;
213 if (data->state != SUCCESS)
216 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
217 "client EAP encryption",
218 EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
220 emsk = os_malloc(EAP_EMSK_LEN);
222 os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
230 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
233 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
240 static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
242 struct eap_tls_data *data = priv;
243 return data->state == SUCCESS;
247 int eap_server_tls_register(void)
249 struct eap_method *eap;
252 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
253 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
257 eap->init = eap_tls_init;
258 eap->reset = eap_tls_reset;
259 eap->buildReq = eap_tls_buildReq;
260 eap->check = eap_tls_check;
261 eap->process = eap_tls_process;
262 eap->isDone = eap_tls_isDone;
263 eap->getKey = eap_tls_getKey;
264 eap->isSuccess = eap_tls_isSuccess;
265 eap->get_emsk = eap_tls_get_emsk;
267 ret = eap_server_method_register(eap);
269 eap_server_method_free(eap);