2 * hostapd / EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "eap_tls_common.h"
14 #include "crypto/tls.h"
17 static void eap_tls_reset(struct eap_sm *sm, void *priv);
21 struct eap_ssl_data ssl;
22 enum { START, CONTINUE, SUCCESS, FAILURE } state;
29 static const char * eap_tls_state_txt(int state)
46 static void eap_tls_state(struct eap_tls_data *data, int state)
48 wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
49 eap_tls_state_txt(data->state),
50 eap_tls_state_txt(state));
53 tls_connection_remove_session(data->ssl.conn);
57 static void eap_tls_valid_session(struct eap_sm *sm, struct eap_tls_data *data)
61 if (!sm->tls_session_lifetime)
64 buf = wpabuf_alloc(1);
67 wpabuf_put_u8(buf, data->eap_type);
68 tls_connection_set_success_data(data->ssl.conn, buf);
72 static void * eap_tls_init(struct eap_sm *sm)
74 struct eap_tls_data *data;
76 data = os_zalloc(sizeof(*data));
81 if (eap_server_tls_ssl_init(sm, &data->ssl, 1, EAP_TYPE_TLS)) {
82 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
83 eap_tls_reset(sm, data);
87 data->eap_type = EAP_TYPE_TLS;
89 data->phase2 = sm->init_phase2;
95 #ifdef EAP_SERVER_UNAUTH_TLS
96 static void * eap_unauth_tls_init(struct eap_sm *sm)
98 struct eap_tls_data *data;
100 data = os_zalloc(sizeof(*data));
105 if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_UNAUTH_TLS_TYPE)) {
106 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
107 eap_tls_reset(sm, data);
111 data->eap_type = EAP_UNAUTH_TLS_TYPE;
114 #endif /* EAP_SERVER_UNAUTH_TLS */
118 static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
120 struct eap_tls_data *data;
122 data = os_zalloc(sizeof(*data));
127 if (eap_server_tls_ssl_init(sm, &data->ssl, 0,
128 EAP_WFA_UNAUTH_TLS_TYPE)) {
129 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
130 eap_tls_reset(sm, data);
134 data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
137 #endif /* CONFIG_HS20 */
140 static void eap_tls_reset(struct eap_sm *sm, void *priv)
142 struct eap_tls_data *data = priv;
145 eap_server_tls_ssl_deinit(sm, &data->ssl);
150 static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
151 struct eap_tls_data *data, u8 id)
155 req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id);
157 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
159 eap_tls_state(data, FAILURE);
163 wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
165 eap_tls_state(data, CONTINUE);
171 static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
173 struct eap_tls_data *data = priv;
176 if (data->ssl.state == FRAG_ACK) {
177 return eap_server_tls_build_ack(id, data->eap_type, 0);
180 if (data->ssl.state == WAIT_FRAG_ACK) {
181 res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0,
183 goto check_established;
186 switch (data->state) {
188 return eap_tls_build_start(sm, data, id);
190 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
191 data->established = 1;
194 wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
195 __func__, data->state);
199 res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id);
202 if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
203 /* TLS handshake has been completed and there are no more
204 * fragments waiting to be sent out. */
205 wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
206 eap_tls_state(data, SUCCESS);
207 eap_tls_valid_session(sm, data);
208 if (sm->serial_num) {
212 user_len = os_snprintf(user, sizeof(user), "cert-%s",
214 if (eap_user_get(sm, (const u8 *) user, user_len,
216 wpa_printf(MSG_DEBUG,
217 "EAP-TLS: No user entry found based on the serial number of the client certificate ");
219 wpa_printf(MSG_DEBUG,
220 "EAP-TLS: Updated user entry based on the serial number of the client certificate ");
228 static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
229 struct wpabuf *respData)
231 struct eap_tls_data *data = priv;
235 if (data->eap_type == EAP_UNAUTH_TLS_TYPE)
236 pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
237 EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
239 else if (data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
240 pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
241 EAP_VENDOR_WFA_UNAUTH_TLS, respData,
244 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type,
246 if (pos == NULL || len < 1) {
247 wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
255 static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
256 const struct wpabuf *respData)
258 struct eap_tls_data *data = priv;
259 if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) {
260 wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
261 "handshake message");
264 if (eap_server_tls_phase1(sm, &data->ssl) < 0)
265 eap_tls_state(data, FAILURE);
269 static void eap_tls_process(struct eap_sm *sm, void *priv,
270 struct wpabuf *respData)
272 struct eap_tls_data *data = priv;
273 const struct wpabuf *buf;
276 if (eap_server_tls_process(sm, &data->ssl, respData, data,
277 data->eap_type, NULL, eap_tls_process_msg) <
279 eap_tls_state(data, FAILURE);
283 if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
284 !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
287 buf = tls_connection_get_success_data(data->ssl.conn);
288 if (!buf || wpabuf_len(buf) < 1) {
289 wpa_printf(MSG_DEBUG,
290 "EAP-TLS: No success data in resumed session - reject attempt");
291 eap_tls_state(data, FAILURE);
295 pos = wpabuf_head(buf);
296 if (*pos != data->eap_type) {
297 wpa_printf(MSG_DEBUG,
298 "EAP-TLS: Resumed session for another EAP type (%u) - reject attempt",
300 eap_tls_state(data, FAILURE);
304 wpa_printf(MSG_DEBUG,
305 "EAP-TLS: Resuming previous session");
306 eap_tls_state(data, SUCCESS);
307 tls_connection_set_success_data_resumed(data->ssl.conn);
308 /* TODO: Cache serial number with session and update EAP user
309 * information based on the cached serial number */
313 static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
315 struct eap_tls_data *data = priv;
316 return data->state == SUCCESS || data->state == FAILURE;
320 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
322 struct eap_tls_data *data = priv;
326 if (data->state != SUCCESS)
329 if (data->ssl.tls_v13)
330 label = "EXPORTER_EAP_TLS_Key_Material";
332 label = "client EAP encryption";
333 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
335 EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
337 *len = EAP_TLS_KEY_LEN;
338 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
339 eapKeyData, EAP_TLS_KEY_LEN);
340 os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
342 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
349 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
351 struct eap_tls_data *data = priv;
352 u8 *eapKeyData, *emsk;
355 if (data->state != SUCCESS)
358 if (data->ssl.tls_v13)
359 label = "EXPORTER_EAP_TLS_Key_Material";
361 label = "client EAP encryption";
362 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
364 EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
366 emsk = os_malloc(EAP_EMSK_LEN);
368 os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
370 bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
376 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
379 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
386 static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
388 struct eap_tls_data *data = priv;
389 return data->state == SUCCESS;
393 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
395 struct eap_tls_data *data = priv;
397 if (data->state != SUCCESS)
400 return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TLS,
405 int eap_server_tls_register(void)
407 struct eap_method *eap;
409 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
410 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
414 eap->init = eap_tls_init;
415 eap->reset = eap_tls_reset;
416 eap->buildReq = eap_tls_buildReq;
417 eap->check = eap_tls_check;
418 eap->process = eap_tls_process;
419 eap->isDone = eap_tls_isDone;
420 eap->getKey = eap_tls_getKey;
421 eap->isSuccess = eap_tls_isSuccess;
422 eap->get_emsk = eap_tls_get_emsk;
423 eap->getSessionId = eap_tls_get_session_id;
425 return eap_server_method_register(eap);
429 #ifdef EAP_SERVER_UNAUTH_TLS
430 int eap_server_unauth_tls_register(void)
432 struct eap_method *eap;
434 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
435 EAP_VENDOR_UNAUTH_TLS,
436 EAP_VENDOR_TYPE_UNAUTH_TLS,
441 eap->init = eap_unauth_tls_init;
442 eap->reset = eap_tls_reset;
443 eap->buildReq = eap_tls_buildReq;
444 eap->check = eap_tls_check;
445 eap->process = eap_tls_process;
446 eap->isDone = eap_tls_isDone;
447 eap->getKey = eap_tls_getKey;
448 eap->isSuccess = eap_tls_isSuccess;
449 eap->get_emsk = eap_tls_get_emsk;
451 return eap_server_method_register(eap);
453 #endif /* EAP_SERVER_UNAUTH_TLS */
457 int eap_server_wfa_unauth_tls_register(void)
459 struct eap_method *eap;
461 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
463 EAP_VENDOR_WFA_UNAUTH_TLS,
468 eap->init = eap_wfa_unauth_tls_init;
469 eap->reset = eap_tls_reset;
470 eap->buildReq = eap_tls_buildReq;
471 eap->check = eap_tls_check;
472 eap->process = eap_tls_process;
473 eap->isDone = eap_tls_isDone;
474 eap->getKey = eap_tls_getKey;
475 eap->isSuccess = eap_tls_isSuccess;
476 eap->get_emsk = eap_tls_get_emsk;
478 return eap_server_method_register(eap);
480 #endif /* CONFIG_HS20 */