2 * hostapd / 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 "crypto/tls.h"
23 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
);
27 struct eap_ssl_data ssl
;
28 enum { START
, CONTINUE
, SUCCESS
, FAILURE
} state
;
33 static const char * eap_tls_state_txt(int state
)
50 static void eap_tls_state(struct eap_tls_data
*data
, int state
)
52 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s -> %s",
53 eap_tls_state_txt(data
->state
),
54 eap_tls_state_txt(state
));
59 static void * eap_tls_init(struct eap_sm
*sm
)
61 struct eap_tls_data
*data
;
63 data
= os_zalloc(sizeof(*data
));
68 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 1)) {
69 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
70 eap_tls_reset(sm
, data
);
78 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
)
80 struct eap_tls_data
*data
= priv
;
83 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
88 static struct wpabuf
* eap_tls_build_start(struct eap_sm
*sm
,
89 struct eap_tls_data
*data
, u8 id
)
93 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TLS
, 1, EAP_CODE_REQUEST
,
96 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to allocate memory for "
98 eap_tls_state(data
, FAILURE
);
102 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
);
104 eap_tls_state(data
, CONTINUE
);
110 static struct wpabuf
* eap_tls_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
112 struct eap_tls_data
*data
= priv
;
115 if (data
->ssl
.state
== FRAG_ACK
) {
116 return eap_server_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
119 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
120 res
= eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TLS
, 0,
122 goto check_established
;
125 switch (data
->state
) {
127 return eap_tls_build_start(sm
, data
, id
);
129 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
))
130 data
->established
= 1;
133 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s - unexpected state %d",
134 __func__
, data
->state
);
138 res
= eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TLS
, 0, id
);
141 if (data
->established
&& data
->ssl
.state
!= WAIT_FRAG_ACK
) {
142 /* TLS handshake has been completed and there are no more
143 * fragments waiting to be sent out. */
144 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
145 eap_tls_state(data
, SUCCESS
);
152 static Boolean
eap_tls_check(struct eap_sm
*sm
, void *priv
,
153 struct wpabuf
*respData
)
158 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TLS
, respData
, &len
);
159 if (pos
== NULL
|| len
< 1) {
160 wpa_printf(MSG_INFO
, "EAP-TLS: Invalid frame");
168 static void eap_tls_process_msg(struct eap_sm
*sm
, void *priv
,
169 const struct wpabuf
*respData
)
171 struct eap_tls_data
*data
= priv
;
172 if (data
->state
== SUCCESS
&& wpabuf_len(data
->ssl
.tls_in
) == 0) {
173 wpa_printf(MSG_DEBUG
, "EAP-TLS: Client acknowledged final TLS "
174 "handshake message");
177 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0)
178 eap_tls_state(data
, FAILURE
);
182 static void eap_tls_process(struct eap_sm
*sm
, void *priv
,
183 struct wpabuf
*respData
)
185 struct eap_tls_data
*data
= priv
;
186 if (eap_server_tls_process(sm
, &data
->ssl
, respData
, data
,
187 EAP_TYPE_TLS
, NULL
, eap_tls_process_msg
) <
189 eap_tls_state(data
, FAILURE
);
193 static Boolean
eap_tls_isDone(struct eap_sm
*sm
, void *priv
)
195 struct eap_tls_data
*data
= priv
;
196 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
200 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
202 struct eap_tls_data
*data
= priv
;
205 if (data
->state
!= SUCCESS
)
208 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
209 "client EAP encryption",
212 *len
= EAP_TLS_KEY_LEN
;
213 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived key",
214 eapKeyData
, EAP_TLS_KEY_LEN
);
216 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive key");
223 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
225 struct eap_tls_data
*data
= priv
;
226 u8
*eapKeyData
, *emsk
;
228 if (data
->state
!= SUCCESS
)
231 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
232 "client EAP encryption",
233 EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
235 emsk
= os_malloc(EAP_EMSK_LEN
);
237 os_memcpy(emsk
, eapKeyData
+ EAP_TLS_KEY_LEN
,
245 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
248 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive EMSK");
255 static Boolean
eap_tls_isSuccess(struct eap_sm
*sm
, void *priv
)
257 struct eap_tls_data
*data
= priv
;
258 return data
->state
== SUCCESS
;
262 int eap_server_tls_register(void)
264 struct eap_method
*eap
;
267 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
268 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
272 eap
->init
= eap_tls_init
;
273 eap
->reset
= eap_tls_reset
;
274 eap
->buildReq
= eap_tls_buildReq
;
275 eap
->check
= eap_tls_check
;
276 eap
->process
= eap_tls_process
;
277 eap
->isDone
= eap_tls_isDone
;
278 eap
->getKey
= eap_tls_getKey
;
279 eap
->isSuccess
= eap_tls_isSuccess
;
280 eap
->get_emsk
= eap_tls_get_emsk
;
282 ret
= eap_server_method_register(eap
);
284 eap_server_method_free(eap
);