2 * EAP peer method: EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2006, 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 "config_ssid.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 wpa_ssid
*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_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_tls_ssl_deinit(sm
, &data
->ssl
);
76 os_free(data
->key_data
);
81 static u8
* eap_tls_failure(struct eap_sm
*sm
, struct eap_tls_data
*data
,
82 struct eap_method_ret
*ret
, int res
, u8
*resp
,
83 u8 id
, size_t *respDataLen
)
85 wpa_printf(MSG_DEBUG
, "EAP-TLS: TLS processing failed");
87 ret
->methodState
= METHOD_DONE
;
88 ret
->decision
= DECISION_FAIL
;
91 struct wpa_ssid
*config
= eap_get_config(sm
);
94 * The TLS handshake failed. So better forget the old
95 * PIN. It may be wrong, we cannot be sure but trying
96 * the wrong one again might block it on the card--so
97 * better ask the user again.
106 * This is likely an alert message, so send it instead of just
112 return eap_tls_build_ack(&data
->ssl
, respDataLen
, id
, EAP_TYPE_TLS
, 0);
116 static void eap_tls_success(struct eap_sm
*sm
, struct eap_tls_data
*data
,
117 struct eap_method_ret
*ret
)
119 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
121 ret
->methodState
= METHOD_DONE
;
122 ret
->decision
= DECISION_UNCOND_SUCC
;
124 os_free(data
->key_data
);
125 data
->key_data
= eap_tls_derive_key(sm
, &data
->ssl
,
126 "client EAP encryption",
127 EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
128 if (data
->key_data
) {
129 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived key",
130 data
->key_data
, EAP_TLS_KEY_LEN
);
131 wpa_hexdump_key(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
132 data
->key_data
+ EAP_TLS_KEY_LEN
,
135 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to derive key");
140 static u8
* eap_tls_process(struct eap_sm
*sm
, void *priv
,
141 struct eap_method_ret
*ret
,
142 const u8
*reqData
, size_t reqDataLen
,
145 const struct eap_hdr
*req
;
150 struct eap_tls_data
*data
= priv
;
152 pos
= eap_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TLS
, ret
,
153 reqData
, reqDataLen
, &left
, &flags
);
156 req
= (const struct eap_hdr
*) reqData
;
157 id
= req
->identifier
;
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_tls_process_helper(sm
, &data
->ssl
, EAP_TYPE_TLS
, 0, id
, pos
,
167 left
, &resp
, respDataLen
);
170 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
);
178 return eap_tls_build_ack(&data
->ssl
, respDataLen
, id
,
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_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_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
);