2 * EAP peer method: EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/tls.h"
14 #include "eap_tls_common.h"
15 #include "eap_config.h"
18 static void eap_tls_deinit(struct eap_sm
*sm
, void *priv
);
22 struct eap_ssl_data ssl
;
28 struct wpabuf
*pending_resp
;
32 static void * eap_tls_init(struct eap_sm
*sm
)
34 struct eap_tls_data
*data
;
35 struct eap_peer_config
*config
= eap_get_config(sm
);
37 ((sm
->init_phase2
? config
->private_key2
: config
->private_key
)
39 (sm
->init_phase2
? config
->engine2
: config
->engine
) == 0)) {
40 wpa_printf(MSG_INFO
, "EAP-TLS: Private key not configured");
44 data
= os_zalloc(sizeof(*data
));
48 data
->ssl_ctx
= sm
->init_phase2
&& sm
->ssl_ctx2
? sm
->ssl_ctx2
:
51 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
, EAP_TYPE_TLS
)) {
52 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
53 eap_tls_deinit(sm
, data
);
55 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting Smartcard "
57 eap_sm_request_pin(sm
);
59 } else if (config
->private_key
&& !config
->private_key_passwd
)
61 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting private "
63 eap_sm_request_passphrase(sm
);
69 data
->eap_type
= EAP_TYPE_TLS
;
76 static void * eap_unauth_tls_init(struct eap_sm
*sm
)
78 struct eap_tls_data
*data
;
79 struct eap_peer_config
*config
= eap_get_config(sm
);
81 data
= os_zalloc(sizeof(*data
));
85 data
->ssl_ctx
= sm
->init_phase2
&& sm
->ssl_ctx2
? sm
->ssl_ctx2
:
88 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
,
89 EAP_UNAUTH_TLS_TYPE
)) {
90 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
91 eap_tls_deinit(sm
, data
);
95 data
->eap_type
= EAP_UNAUTH_TLS_TYPE
;
99 #endif /* EAP_UNAUTH_TLS */
103 static void * eap_wfa_unauth_tls_init(struct eap_sm
*sm
)
105 struct eap_tls_data
*data
;
106 struct eap_peer_config
*config
= eap_get_config(sm
);
108 data
= os_zalloc(sizeof(*data
));
112 data
->ssl_ctx
= sm
->init_phase2
&& sm
->ssl_ctx2
? sm
->ssl_ctx2
:
115 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
,
116 EAP_WFA_UNAUTH_TLS_TYPE
)) {
117 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
118 eap_tls_deinit(sm
, data
);
122 data
->eap_type
= EAP_WFA_UNAUTH_TLS_TYPE
;
126 #endif /* CONFIG_HS20 */
129 static void eap_tls_free_key(struct eap_tls_data
*data
)
131 if (data
->key_data
) {
132 bin_clear_free(data
->key_data
, EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
133 data
->key_data
= NULL
;
138 static void eap_tls_deinit(struct eap_sm
*sm
, void *priv
)
140 struct eap_tls_data
*data
= priv
;
143 eap_peer_tls_ssl_deinit(sm
, &data
->ssl
);
144 eap_tls_free_key(data
);
145 os_free(data
->session_id
);
146 wpabuf_free(data
->pending_resp
);
151 static struct wpabuf
* eap_tls_failure(struct eap_sm
*sm
,
152 struct eap_tls_data
*data
,
153 struct eap_method_ret
*ret
, int res
,
154 struct wpabuf
*resp
, u8 id
)
156 wpa_printf(MSG_DEBUG
, "EAP-TLS: TLS processing failed");
158 ret
->methodState
= METHOD_DONE
;
159 ret
->decision
= DECISION_FAIL
;
163 * This is likely an alert message, so send it instead of just
169 return eap_peer_tls_build_ack(id
, data
->eap_type
, 0);
173 static void eap_tls_success(struct eap_sm
*sm
, struct eap_tls_data
*data
,
174 struct eap_method_ret
*ret
)
176 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
178 if (data
->ssl
.tls_out
) {
179 wpa_printf(MSG_DEBUG
, "EAP-TLS: Fragment(s) remaining");
183 ret
->methodState
= METHOD_DONE
;
184 ret
->decision
= DECISION_UNCOND_SUCC
;
186 eap_tls_free_key(data
);
187 data
->key_data
= eap_peer_tls_derive_key(sm
, &data
->ssl
,
188 "client EAP encryption",
191 if (data
->key_data
) {
192 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived key",
193 data
->key_data
, EAP_TLS_KEY_LEN
);
194 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
195 data
->key_data
+ EAP_TLS_KEY_LEN
,
198 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to derive key");
201 os_free(data
->session_id
);
202 data
->session_id
= eap_peer_tls_derive_session_id(sm
, &data
->ssl
,
205 if (data
->session_id
) {
206 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived Session-Id",
207 data
->session_id
, data
->id_len
);
209 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to derive Session-Id");
214 static struct wpabuf
* eap_tls_process(struct eap_sm
*sm
, void *priv
,
215 struct eap_method_ret
*ret
,
216 const struct wpabuf
*reqData
)
223 struct eap_tls_data
*data
= priv
;
226 if (sm
->waiting_ext_cert_check
&& data
->pending_resp
) {
227 struct eap_peer_config
*config
= eap_get_config(sm
);
229 if (config
->pending_ext_cert_check
== EXT_CERT_CHECK_GOOD
) {
230 wpa_printf(MSG_DEBUG
,
231 "EAP-TLS: External certificate check succeeded - continue handshake");
232 resp
= data
->pending_resp
;
233 data
->pending_resp
= NULL
;
234 sm
->waiting_ext_cert_check
= 0;
238 if (config
->pending_ext_cert_check
== EXT_CERT_CHECK_BAD
) {
239 wpa_printf(MSG_DEBUG
,
240 "EAP-TLS: External certificate check failed - force authentication failure");
241 ret
->methodState
= METHOD_DONE
;
242 ret
->decision
= DECISION_FAIL
;
243 sm
->waiting_ext_cert_check
= 0;
247 wpa_printf(MSG_DEBUG
,
248 "EAP-TLS: Continuing to wait external server certificate validation");
252 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, data
->eap_type
, ret
,
253 reqData
, &left
, &flags
);
256 id
= eap_get_id(reqData
);
258 if (flags
& EAP_TLS_FLAGS_START
) {
259 wpa_printf(MSG_DEBUG
, "EAP-TLS: Start");
260 left
= 0; /* make sure that this frame is empty, even though it
261 * should always be, anyway */
265 wpabuf_set(&msg
, pos
, left
);
266 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
, data
->eap_type
, 0,
270 return eap_tls_failure(sm
, data
, ret
, res
, resp
, id
);
273 if (sm
->waiting_ext_cert_check
) {
274 wpa_printf(MSG_DEBUG
,
275 "EAP-TLS: Waiting external server certificate validation");
276 wpabuf_free(data
->pending_resp
);
277 data
->pending_resp
= resp
;
281 if (tls_connection_established(data
->ssl_ctx
, data
->ssl
.conn
))
282 eap_tls_success(sm
, data
, ret
);
286 return eap_peer_tls_build_ack(id
, data
->eap_type
, 0);
293 static Boolean
eap_tls_has_reauth_data(struct eap_sm
*sm
, void *priv
)
295 struct eap_tls_data
*data
= priv
;
296 return tls_connection_established(data
->ssl_ctx
, data
->ssl
.conn
);
300 static void eap_tls_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
302 struct eap_tls_data
*data
= priv
;
304 wpabuf_free(data
->pending_resp
);
305 data
->pending_resp
= NULL
;
309 static void * eap_tls_init_for_reauth(struct eap_sm
*sm
, void *priv
)
311 struct eap_tls_data
*data
= priv
;
312 eap_tls_free_key(data
);
313 os_free(data
->session_id
);
314 data
->session_id
= NULL
;
315 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
323 static int eap_tls_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
324 size_t buflen
, int verbose
)
326 struct eap_tls_data
*data
= priv
;
327 return eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
331 static Boolean
eap_tls_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
333 struct eap_tls_data
*data
= priv
;
334 return data
->key_data
!= NULL
;
338 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
340 struct eap_tls_data
*data
= priv
;
343 if (data
->key_data
== NULL
)
346 key
= os_memdup(data
->key_data
, EAP_TLS_KEY_LEN
);
350 *len
= EAP_TLS_KEY_LEN
;
356 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
358 struct eap_tls_data
*data
= priv
;
361 if (data
->key_data
== NULL
)
364 key
= os_memdup(data
->key_data
+ EAP_TLS_KEY_LEN
, EAP_EMSK_LEN
);
374 static u8
* eap_tls_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
376 struct eap_tls_data
*data
= priv
;
379 if (data
->session_id
== NULL
)
382 id
= os_memdup(data
->session_id
, data
->id_len
);
392 int eap_peer_tls_register(void)
394 struct eap_method
*eap
;
396 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
397 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
401 eap
->init
= eap_tls_init
;
402 eap
->deinit
= eap_tls_deinit
;
403 eap
->process
= eap_tls_process
;
404 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
405 eap
->getKey
= eap_tls_getKey
;
406 eap
->getSessionId
= eap_tls_get_session_id
;
407 eap
->get_status
= eap_tls_get_status
;
408 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
409 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
410 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
411 eap
->get_emsk
= eap_tls_get_emsk
;
413 return eap_peer_method_register(eap
);
417 #ifdef EAP_UNAUTH_TLS
418 int eap_peer_unauth_tls_register(void)
420 struct eap_method
*eap
;
422 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
423 EAP_VENDOR_UNAUTH_TLS
,
424 EAP_VENDOR_TYPE_UNAUTH_TLS
, "UNAUTH-TLS");
428 eap
->init
= eap_unauth_tls_init
;
429 eap
->deinit
= eap_tls_deinit
;
430 eap
->process
= eap_tls_process
;
431 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
432 eap
->getKey
= eap_tls_getKey
;
433 eap
->get_status
= eap_tls_get_status
;
434 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
435 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
436 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
437 eap
->get_emsk
= eap_tls_get_emsk
;
439 return eap_peer_method_register(eap
);
441 #endif /* EAP_UNAUTH_TLS */
445 int eap_peer_wfa_unauth_tls_register(void)
447 struct eap_method
*eap
;
449 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
451 EAP_VENDOR_WFA_UNAUTH_TLS
,
456 eap
->init
= eap_wfa_unauth_tls_init
;
457 eap
->deinit
= eap_tls_deinit
;
458 eap
->process
= eap_tls_process
;
459 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
460 eap
->getKey
= eap_tls_getKey
;
461 eap
->get_status
= eap_tls_get_status
;
462 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
463 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
464 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
465 eap
->get_emsk
= eap_tls_get_emsk
;
467 return eap_peer_method_register(eap
);
469 #endif /* CONFIG_HS20 */