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 ret
->methodState
= METHOD_DONE
;
179 ret
->decision
= DECISION_UNCOND_SUCC
;
181 eap_tls_free_key(data
);
182 data
->key_data
= eap_peer_tls_derive_key(sm
, &data
->ssl
,
183 "client EAP encryption",
186 if (data
->key_data
) {
187 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived key",
188 data
->key_data
, EAP_TLS_KEY_LEN
);
189 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
190 data
->key_data
+ EAP_TLS_KEY_LEN
,
193 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to derive key");
196 os_free(data
->session_id
);
197 data
->session_id
= eap_peer_tls_derive_session_id(sm
, &data
->ssl
,
200 if (data
->session_id
) {
201 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived Session-Id",
202 data
->session_id
, data
->id_len
);
204 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to derive Session-Id");
209 static struct wpabuf
* eap_tls_process(struct eap_sm
*sm
, void *priv
,
210 struct eap_method_ret
*ret
,
211 const struct wpabuf
*reqData
)
218 struct eap_tls_data
*data
= priv
;
221 if (sm
->waiting_ext_cert_check
&& data
->pending_resp
) {
222 struct eap_peer_config
*config
= eap_get_config(sm
);
224 if (config
->pending_ext_cert_check
== EXT_CERT_CHECK_GOOD
) {
225 wpa_printf(MSG_DEBUG
,
226 "EAP-TLS: External certificate check succeeded - continue handshake");
227 resp
= data
->pending_resp
;
228 data
->pending_resp
= NULL
;
229 sm
->waiting_ext_cert_check
= 0;
233 if (config
->pending_ext_cert_check
== EXT_CERT_CHECK_BAD
) {
234 wpa_printf(MSG_DEBUG
,
235 "EAP-TLS: External certificate check failed - force authentication failure");
236 ret
->methodState
= METHOD_DONE
;
237 ret
->decision
= DECISION_FAIL
;
238 sm
->waiting_ext_cert_check
= 0;
242 wpa_printf(MSG_DEBUG
,
243 "EAP-TLS: Continuing to wait external server certificate validation");
247 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, data
->eap_type
, ret
,
248 reqData
, &left
, &flags
);
251 id
= eap_get_id(reqData
);
253 if (flags
& EAP_TLS_FLAGS_START
) {
254 wpa_printf(MSG_DEBUG
, "EAP-TLS: Start");
255 left
= 0; /* make sure that this frame is empty, even though it
256 * should always be, anyway */
260 wpabuf_set(&msg
, pos
, left
);
261 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
, data
->eap_type
, 0,
265 return eap_tls_failure(sm
, data
, ret
, res
, resp
, id
);
268 if (sm
->waiting_ext_cert_check
) {
269 wpa_printf(MSG_DEBUG
,
270 "EAP-TLS: Waiting external server certificate validation");
271 wpabuf_free(data
->pending_resp
);
272 data
->pending_resp
= resp
;
276 if (tls_connection_established(data
->ssl_ctx
, data
->ssl
.conn
))
277 eap_tls_success(sm
, data
, ret
);
281 return eap_peer_tls_build_ack(id
, data
->eap_type
, 0);
288 static Boolean
eap_tls_has_reauth_data(struct eap_sm
*sm
, void *priv
)
290 struct eap_tls_data
*data
= priv
;
291 return tls_connection_established(data
->ssl_ctx
, data
->ssl
.conn
);
295 static void eap_tls_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
297 struct eap_tls_data
*data
= priv
;
299 wpabuf_free(data
->pending_resp
);
300 data
->pending_resp
= NULL
;
304 static void * eap_tls_init_for_reauth(struct eap_sm
*sm
, void *priv
)
306 struct eap_tls_data
*data
= priv
;
307 eap_tls_free_key(data
);
308 os_free(data
->session_id
);
309 data
->session_id
= NULL
;
310 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
318 static int eap_tls_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
319 size_t buflen
, int verbose
)
321 struct eap_tls_data
*data
= priv
;
322 return eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
326 static Boolean
eap_tls_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
328 struct eap_tls_data
*data
= priv
;
329 return data
->key_data
!= NULL
;
333 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
335 struct eap_tls_data
*data
= priv
;
338 if (data
->key_data
== NULL
)
341 key
= os_malloc(EAP_TLS_KEY_LEN
);
345 *len
= EAP_TLS_KEY_LEN
;
346 os_memcpy(key
, data
->key_data
, EAP_TLS_KEY_LEN
);
352 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
354 struct eap_tls_data
*data
= priv
;
357 if (data
->key_data
== NULL
)
360 key
= os_malloc(EAP_EMSK_LEN
);
365 os_memcpy(key
, data
->key_data
+ EAP_TLS_KEY_LEN
, EAP_EMSK_LEN
);
371 static u8
* eap_tls_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
373 struct eap_tls_data
*data
= priv
;
376 if (data
->session_id
== NULL
)
379 id
= os_malloc(data
->id_len
);
384 os_memcpy(id
, data
->session_id
, data
->id_len
);
390 int eap_peer_tls_register(void)
392 struct eap_method
*eap
;
394 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
395 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
399 eap
->init
= eap_tls_init
;
400 eap
->deinit
= eap_tls_deinit
;
401 eap
->process
= eap_tls_process
;
402 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
403 eap
->getKey
= eap_tls_getKey
;
404 eap
->getSessionId
= eap_tls_get_session_id
;
405 eap
->get_status
= eap_tls_get_status
;
406 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
407 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
408 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
409 eap
->get_emsk
= eap_tls_get_emsk
;
411 return eap_peer_method_register(eap
);
415 #ifdef EAP_UNAUTH_TLS
416 int eap_peer_unauth_tls_register(void)
418 struct eap_method
*eap
;
420 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
421 EAP_VENDOR_UNAUTH_TLS
,
422 EAP_VENDOR_TYPE_UNAUTH_TLS
, "UNAUTH-TLS");
426 eap
->init
= eap_unauth_tls_init
;
427 eap
->deinit
= eap_tls_deinit
;
428 eap
->process
= eap_tls_process
;
429 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
430 eap
->getKey
= eap_tls_getKey
;
431 eap
->get_status
= eap_tls_get_status
;
432 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
433 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
434 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
435 eap
->get_emsk
= eap_tls_get_emsk
;
437 return eap_peer_method_register(eap
);
439 #endif /* EAP_UNAUTH_TLS */
443 int eap_peer_wfa_unauth_tls_register(void)
445 struct eap_method
*eap
;
447 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
449 EAP_VENDOR_WFA_UNAUTH_TLS
,
454 eap
->init
= eap_wfa_unauth_tls_init
;
455 eap
->deinit
= eap_tls_deinit
;
456 eap
->process
= eap_tls_process
;
457 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
458 eap
->getKey
= eap_tls_getKey
;
459 eap
->get_status
= eap_tls_get_status
;
460 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
461 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
462 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
463 eap
->get_emsk
= eap_tls_get_emsk
;
465 return eap_peer_method_register(eap
);
467 #endif /* CONFIG_HS20 */