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.
18 #include "crypto/tls.h"
20 #include "eap_tls_common.h"
21 #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
)
40 (sm
->init_phase2
? config
->engine2
: config
->engine
) == 0)) {
41 wpa_printf(MSG_INFO
, "EAP-TLS: Private key not configured");
45 data
= os_zalloc(sizeof(*data
));
49 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
)) {
50 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
51 eap_tls_deinit(sm
, data
);
53 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting Smartcard "
55 eap_sm_request_pin(sm
);
57 } else if (config
->private_key
&& !config
->private_key_passwd
)
59 wpa_printf(MSG_DEBUG
, "EAP-TLS: Requesting private "
61 eap_sm_request_passphrase(sm
);
71 static void eap_tls_deinit(struct eap_sm
*sm
, void *priv
)
73 struct eap_tls_data
*data
= priv
;
76 eap_peer_tls_ssl_deinit(sm
, &data
->ssl
);
77 os_free(data
->key_data
);
82 static struct wpabuf
* eap_tls_failure(struct eap_sm
*sm
,
83 struct eap_tls_data
*data
,
84 struct eap_method_ret
*ret
, int res
,
85 struct wpabuf
*resp
, u8 id
)
87 wpa_printf(MSG_DEBUG
, "EAP-TLS: TLS processing failed");
89 ret
->methodState
= METHOD_DONE
;
90 ret
->decision
= DECISION_FAIL
;
93 struct eap_peer_config
*config
= eap_get_config(sm
);
96 * The TLS handshake failed. So better forget the old
97 * PIN. It may be wrong, we cannot be sure but trying
98 * the wrong one again might block it on the card--so
99 * better ask the user again.
101 os_free(config
->pin
);
108 * This is likely an alert message, so send it instead of just
114 return eap_peer_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
118 static void eap_tls_success(struct eap_sm
*sm
, struct eap_tls_data
*data
,
119 struct eap_method_ret
*ret
)
121 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
123 ret
->methodState
= METHOD_DONE
;
124 ret
->decision
= DECISION_UNCOND_SUCC
;
126 os_free(data
->key_data
);
127 data
->key_data
= eap_peer_tls_derive_key(sm
, &data
->ssl
,
128 "client EAP encryption",
131 if (data
->key_data
) {
132 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived key",
133 data
->key_data
, EAP_TLS_KEY_LEN
);
134 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
135 data
->key_data
+ EAP_TLS_KEY_LEN
,
138 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to derive key");
143 static struct wpabuf
* eap_tls_process(struct eap_sm
*sm
, void *priv
,
144 struct eap_method_ret
*ret
,
145 const struct wpabuf
*reqData
)
152 struct eap_tls_data
*data
= priv
;
154 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TLS
, ret
,
155 reqData
, &left
, &flags
);
158 id
= eap_get_id(reqData
);
160 if (flags
& EAP_TLS_FLAGS_START
) {
161 wpa_printf(MSG_DEBUG
, "EAP-TLS: Start");
162 left
= 0; /* make sure that this frame is empty, even though it
163 * should always be, anyway */
167 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
, EAP_TYPE_TLS
, 0, id
,
171 return eap_tls_failure(sm
, data
, ret
, res
, resp
, id
);
174 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
))
175 eap_tls_success(sm
, data
, ret
);
179 return eap_peer_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
186 static Boolean
eap_tls_has_reauth_data(struct eap_sm
*sm
, void *priv
)
188 struct eap_tls_data
*data
= priv
;
189 return tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
);
193 static void eap_tls_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
198 static void * eap_tls_init_for_reauth(struct eap_sm
*sm
, void *priv
)
200 struct eap_tls_data
*data
= priv
;
201 os_free(data
->key_data
);
202 data
->key_data
= NULL
;
203 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
211 static int eap_tls_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
212 size_t buflen
, int verbose
)
214 struct eap_tls_data
*data
= priv
;
215 return eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
219 static Boolean
eap_tls_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
221 struct eap_tls_data
*data
= priv
;
222 return data
->key_data
!= NULL
;
226 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
228 struct eap_tls_data
*data
= priv
;
231 if (data
->key_data
== NULL
)
234 key
= os_malloc(EAP_TLS_KEY_LEN
);
238 *len
= EAP_TLS_KEY_LEN
;
239 os_memcpy(key
, data
->key_data
, EAP_TLS_KEY_LEN
);
245 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
247 struct eap_tls_data
*data
= priv
;
250 if (data
->key_data
== NULL
)
253 key
= os_malloc(EAP_EMSK_LEN
);
258 os_memcpy(key
, data
->key_data
+ EAP_TLS_KEY_LEN
, EAP_EMSK_LEN
);
264 int eap_peer_tls_register(void)
266 struct eap_method
*eap
;
269 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
270 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
274 eap
->init
= eap_tls_init
;
275 eap
->deinit
= eap_tls_deinit
;
276 eap
->process
= eap_tls_process
;
277 eap
->isKeyAvailable
= eap_tls_isKeyAvailable
;
278 eap
->getKey
= eap_tls_getKey
;
279 eap
->get_status
= eap_tls_get_status
;
280 eap
->has_reauth_data
= eap_tls_has_reauth_data
;
281 eap
->deinit_for_reauth
= eap_tls_deinit_for_reauth
;
282 eap
->init_for_reauth
= eap_tls_init_for_reauth
;
283 eap
->get_emsk
= eap_tls_get_emsk
;
285 ret
= eap_peer_method_register(eap
);
287 eap_peer_method_free(eap
);