2 * EAP peer method: 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"
20 #include "eap_config.h"
24 static void eap_tls_deinit(struct eap_sm
*sm
, void *priv
);
28 struct eap_ssl_data ssl
;
33 static void * eap_tls_init(struct eap_sm
*sm
)
35 struct eap_tls_data
*data
;
36 struct eap_peer_config
*config
= eap_get_config(sm
);
38 ((sm
->init_phase2
? config
->private_key2
: config
->private_key
)
39 == NULL
&& config
->engine
== 0)) {
40 wpa_printf(MSG_INFO
, "EAP-TLS: Private key not configured");
44 data
= os_zalloc(sizeof(*data
));
48 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
)) {
49 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
50 eap_tls_deinit(sm
, data
);
52 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting Smartcard "
54 eap_sm_request_pin(sm
);
56 } else if (config
->private_key
&& !config
->private_key_passwd
)
58 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting private "
60 eap_sm_request_passphrase(sm
);
70 static void eap_tls_deinit(struct eap_sm
*sm
, void *priv
)
72 struct eap_tls_data
*data
= priv
;
75 eap_peer_tls_ssl_deinit(sm
, &data
->ssl
);
76 os_free(data
->key_data
);
81 static struct wpabuf
* eap_tls_failure(struct eap_sm
*sm
,
82 struct eap_tls_data
*data
,
83 struct eap_method_ret
*ret
, int res
,
84 struct wpabuf
*resp
, u8 id
)
86 wpa_printf(MSG_DEBUG
, "EAP-TLS: TLS processing failed");
88 ret
->methodState
= METHOD_DONE
;
89 ret
->decision
= DECISION_FAIL
;
92 struct eap_peer_config
*config
= eap_get_config(sm
);
95 * The TLS handshake failed. So better forget the old
96 * PIN. It may be wrong, we cannot be sure but trying
97 * the wrong one again might block it on the card--so
98 * better ask the user again.
100 os_free(config
->pin
);
107 * This is likely an alert message, so send it instead of just
113 return eap_peer_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
117 static void eap_tls_success(struct eap_sm
*sm
, struct eap_tls_data
*data
,
118 struct eap_method_ret
*ret
)
120 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
122 ret
->methodState
= METHOD_DONE
;
123 ret
->decision
= DECISION_UNCOND_SUCC
;
125 os_free(data
->key_data
);
126 data
->key_data
= eap_peer_tls_derive_key(sm
, &data
->ssl
,
127 "client EAP encryption",
130 if (data
->key_data
) {
131 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived key",
132 data
->key_data
, EAP_TLS_KEY_LEN
);
133 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
134 data
->key_data
+ EAP_TLS_KEY_LEN
,
137 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to derive key");
142 static struct wpabuf
* eap_tls_process(struct eap_sm
*sm
, void *priv
,
143 struct eap_method_ret
*ret
,
144 const struct wpabuf
*reqData
)
151 struct eap_tls_data
*data
= priv
;
153 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TLS
, ret
,
154 reqData
, &left
, &flags
);
157 id
= eap_get_id(reqData
);
159 if (flags
& EAP_TLS_FLAGS_START
) {
160 wpa_printf(MSG_DEBUG
, "EAP-TLS: Start");
161 left
= 0; /* make sure that this frame is empty, even though it
162 * should always be, anyway */
166 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
, EAP_TYPE_TLS
, 0, id
,
170 return eap_tls_failure(sm
, data
, ret
, res
, resp
, id
);
173 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
))
174 eap_tls_success(sm
, data
, ret
);
178 return eap_peer_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
185 static Boolean
eap_tls_has_reauth_data(struct eap_sm
*sm
, void *priv
)
187 struct eap_tls_data
*data
= priv
;
188 return tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
);
192 static void eap_tls_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
197 static void * eap_tls_init_for_reauth(struct eap_sm
*sm
, void *priv
)
199 struct eap_tls_data
*data
= priv
;
200 os_free(data
->key_data
);
201 data
->key_data
= NULL
;
202 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
210 static int eap_tls_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
211 size_t buflen
, int verbose
)
213 struct eap_tls_data
*data
= priv
;
214 return eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
218 static Boolean
eap_tls_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
220 struct eap_tls_data
*data
= priv
;
221 return data
->key_data
!= NULL
;
225 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
227 struct eap_tls_data
*data
= priv
;
230 if (data
->key_data
== NULL
)
233 key
= os_malloc(EAP_TLS_KEY_LEN
);
237 *len
= EAP_TLS_KEY_LEN
;
238 os_memcpy(key
, data
->key_data
, EAP_TLS_KEY_LEN
);
244 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
246 struct eap_tls_data
*data
= priv
;
249 if (data
->key_data
== NULL
)
252 key
= os_malloc(EAP_EMSK_LEN
);
257 os_memcpy(key
, data
->key_data
+ EAP_TLS_KEY_LEN
, EAP_EMSK_LEN
);
263 int eap_peer_tls_register(void)
265 struct eap_method
*eap
;
268 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
269 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
273 eap
->init
= eap_tls_init
;
274 eap
->deinit
= eap_tls_deinit
;
275 eap
->process
= eap_tls_process
;
276 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
277 eap
->getKey
= eap_tls_getKey
;
278 eap
->get_status
= eap_tls_get_status
;
279 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
280 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
281 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
282 eap
->get_emsk
= eap_tls_get_emsk
;
284 ret
= eap_peer_method_register(eap
);
286 eap_peer_method_free(eap
);