2 * hostapd / EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "eap_tls_common.h"
14 #include "crypto/tls.h"
17 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
);
21 struct eap_ssl_data ssl
;
22 enum { START
, CONTINUE
, SUCCESS
, FAILURE
} state
;
28 static const char * eap_tls_state_txt(int state
)
45 static void eap_tls_state(struct eap_tls_data
*data
, int state
)
47 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s -> %s",
48 eap_tls_state_txt(data
->state
),
49 eap_tls_state_txt(state
));
54 static void * eap_tls_init(struct eap_sm
*sm
)
56 struct eap_tls_data
*data
;
58 data
= os_zalloc(sizeof(*data
));
63 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 1, EAP_TYPE_TLS
)) {
64 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
65 eap_tls_reset(sm
, data
);
69 data
->eap_type
= EAP_TYPE_TLS
;
75 #ifdef EAP_SERVER_UNAUTH_TLS
76 static void * eap_unauth_tls_init(struct eap_sm
*sm
)
78 struct eap_tls_data
*data
;
80 data
= os_zalloc(sizeof(*data
));
85 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0, EAP_UNAUTH_TLS_TYPE
)) {
86 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
87 eap_tls_reset(sm
, data
);
91 data
->eap_type
= EAP_UNAUTH_TLS_TYPE
;
94 #endif /* EAP_SERVER_UNAUTH_TLS */
98 static void * eap_wfa_unauth_tls_init(struct eap_sm
*sm
)
100 struct eap_tls_data
*data
;
102 data
= os_zalloc(sizeof(*data
));
107 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0,
108 EAP_WFA_UNAUTH_TLS_TYPE
)) {
109 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
110 eap_tls_reset(sm
, data
);
114 data
->eap_type
= EAP_WFA_UNAUTH_TLS_TYPE
;
117 #endif /* CONFIG_HS20 */
120 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
)
122 struct eap_tls_data
*data
= priv
;
125 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
130 static struct wpabuf
* eap_tls_build_start(struct eap_sm
*sm
,
131 struct eap_tls_data
*data
, u8 id
)
135 req
= eap_tls_msg_alloc(data
->eap_type
, 1, EAP_CODE_REQUEST
, id
);
137 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to allocate memory for "
139 eap_tls_state(data
, FAILURE
);
143 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
);
145 eap_tls_state(data
, CONTINUE
);
151 static struct wpabuf
* eap_tls_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
153 struct eap_tls_data
*data
= priv
;
156 if (data
->ssl
.state
== FRAG_ACK
) {
157 return eap_server_tls_build_ack(id
, data
->eap_type
, 0);
160 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
161 res
= eap_server_tls_build_msg(&data
->ssl
, data
->eap_type
, 0,
163 goto check_established
;
166 switch (data
->state
) {
168 return eap_tls_build_start(sm
, data
, id
);
170 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
))
171 data
->established
= 1;
174 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s - unexpected state %d",
175 __func__
, data
->state
);
179 res
= eap_server_tls_build_msg(&data
->ssl
, data
->eap_type
, 0, id
);
182 if (data
->established
&& data
->ssl
.state
!= WAIT_FRAG_ACK
) {
183 /* TLS handshake has been completed and there are no more
184 * fragments waiting to be sent out. */
185 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
186 eap_tls_state(data
, SUCCESS
);
193 static Boolean
eap_tls_check(struct eap_sm
*sm
, void *priv
,
194 struct wpabuf
*respData
)
196 struct eap_tls_data
*data
= priv
;
200 if (data
->eap_type
== EAP_UNAUTH_TLS_TYPE
)
201 pos
= eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS
,
202 EAP_VENDOR_TYPE_UNAUTH_TLS
, respData
,
204 else if (data
->eap_type
== EAP_WFA_UNAUTH_TLS_TYPE
)
205 pos
= eap_hdr_validate(EAP_VENDOR_WFA_NEW
,
206 EAP_VENDOR_WFA_UNAUTH_TLS
, respData
,
209 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, data
->eap_type
,
211 if (pos
== NULL
|| len
< 1) {
212 wpa_printf(MSG_INFO
, "EAP-TLS: Invalid frame");
220 static void eap_tls_process_msg(struct eap_sm
*sm
, void *priv
,
221 const struct wpabuf
*respData
)
223 struct eap_tls_data
*data
= priv
;
224 if (data
->state
== SUCCESS
&& wpabuf_len(data
->ssl
.tls_in
) == 0) {
225 wpa_printf(MSG_DEBUG
, "EAP-TLS: Client acknowledged final TLS "
226 "handshake message");
229 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0)
230 eap_tls_state(data
, FAILURE
);
234 static void eap_tls_process(struct eap_sm
*sm
, void *priv
,
235 struct wpabuf
*respData
)
237 struct eap_tls_data
*data
= priv
;
238 if (eap_server_tls_process(sm
, &data
->ssl
, respData
, data
,
239 data
->eap_type
, NULL
, eap_tls_process_msg
) <
241 eap_tls_state(data
, FAILURE
);
245 static Boolean
eap_tls_isDone(struct eap_sm
*sm
, void *priv
)
247 struct eap_tls_data
*data
= priv
;
248 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
252 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
254 struct eap_tls_data
*data
= priv
;
257 if (data
->state
!= SUCCESS
)
260 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
261 "client EAP encryption",
264 *len
= EAP_TLS_KEY_LEN
;
265 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived key",
266 eapKeyData
, EAP_TLS_KEY_LEN
);
268 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive key");
275 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
277 struct eap_tls_data
*data
= priv
;
278 u8
*eapKeyData
, *emsk
;
280 if (data
->state
!= SUCCESS
)
283 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
284 "client EAP encryption",
285 EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
287 emsk
= os_malloc(EAP_EMSK_LEN
);
289 os_memcpy(emsk
, eapKeyData
+ EAP_TLS_KEY_LEN
,
291 bin_clear_free(eapKeyData
, EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
297 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
300 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive EMSK");
307 static Boolean
eap_tls_isSuccess(struct eap_sm
*sm
, void *priv
)
309 struct eap_tls_data
*data
= priv
;
310 return data
->state
== SUCCESS
;
314 static u8
* eap_tls_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
316 struct eap_tls_data
*data
= priv
;
318 if (data
->state
!= SUCCESS
)
321 return eap_server_tls_derive_session_id(sm
, &data
->ssl
, EAP_TYPE_TLS
,
326 int eap_server_tls_register(void)
328 struct eap_method
*eap
;
331 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
332 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
336 eap
->init
= eap_tls_init
;
337 eap
->reset
= eap_tls_reset
;
338 eap
->buildReq
= eap_tls_buildReq
;
339 eap
->check
= eap_tls_check
;
340 eap
->process
= eap_tls_process
;
341 eap
->isDone
= eap_tls_isDone
;
342 eap
->getKey
= eap_tls_getKey
;
343 eap
->isSuccess
= eap_tls_isSuccess
;
344 eap
->get_emsk
= eap_tls_get_emsk
;
345 eap
->getSessionId
= eap_tls_get_session_id
;
347 ret
= eap_server_method_register(eap
);
349 eap_server_method_free(eap
);
354 #ifdef EAP_SERVER_UNAUTH_TLS
355 int eap_server_unauth_tls_register(void)
357 struct eap_method
*eap
;
360 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
361 EAP_VENDOR_UNAUTH_TLS
,
362 EAP_VENDOR_TYPE_UNAUTH_TLS
,
367 eap
->init
= eap_unauth_tls_init
;
368 eap
->reset
= eap_tls_reset
;
369 eap
->buildReq
= eap_tls_buildReq
;
370 eap
->check
= eap_tls_check
;
371 eap
->process
= eap_tls_process
;
372 eap
->isDone
= eap_tls_isDone
;
373 eap
->getKey
= eap_tls_getKey
;
374 eap
->isSuccess
= eap_tls_isSuccess
;
375 eap
->get_emsk
= eap_tls_get_emsk
;
377 ret
= eap_server_method_register(eap
);
379 eap_server_method_free(eap
);
382 #endif /* EAP_SERVER_UNAUTH_TLS */
386 int eap_server_wfa_unauth_tls_register(void)
388 struct eap_method
*eap
;
391 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
393 EAP_VENDOR_WFA_UNAUTH_TLS
,
398 eap
->init
= eap_wfa_unauth_tls_init
;
399 eap
->reset
= eap_tls_reset
;
400 eap
->buildReq
= eap_tls_buildReq
;
401 eap
->check
= eap_tls_check
;
402 eap
->process
= eap_tls_process
;
403 eap
->isDone
= eap_tls_isDone
;
404 eap
->getKey
= eap_tls_getKey
;
405 eap
->isSuccess
= eap_tls_isSuccess
;
406 eap
->get_emsk
= eap_tls_get_emsk
;
408 ret
= eap_server_method_register(eap
);
410 eap_server_method_free(eap
);
413 #endif /* CONFIG_HS20 */