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"
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
;
32 static const char * eap_tls_state_txt(int state
)
49 static void eap_tls_state(struct eap_tls_data
*data
, int state
)
51 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s -> %s",
52 eap_tls_state_txt(data
->state
),
53 eap_tls_state_txt(state
));
58 static void * eap_tls_init(struct eap_sm
*sm
)
60 struct eap_tls_data
*data
;
62 data
= os_zalloc(sizeof(*data
));
67 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 1)) {
68 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
69 eap_tls_reset(sm
, data
);
77 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
)
79 struct eap_tls_data
*data
= priv
;
82 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
87 static struct wpabuf
* eap_tls_build_start(struct eap_sm
*sm
,
88 struct eap_tls_data
*data
, u8 id
)
92 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TLS
, 1, EAP_CODE_REQUEST
,
95 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to allocate memory for "
97 eap_tls_state(data
, FAILURE
);
101 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
);
103 eap_tls_state(data
, CONTINUE
);
109 static struct wpabuf
* eap_tls_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
111 struct eap_tls_data
*data
= priv
;
114 if (data
->ssl
.state
== FRAG_ACK
) {
115 return eap_server_tls_build_ack(id
, EAP_TYPE_TLS
, 0);
118 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
119 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TLS
, 0,
123 switch (data
->state
) {
125 return eap_tls_build_start(sm
, data
, id
);
127 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
128 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
129 eap_tls_state(data
, SUCCESS
);
133 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s - unexpected state %d",
134 __func__
, data
->state
);
138 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TLS
, 0, id
);
142 static Boolean
eap_tls_check(struct eap_sm
*sm
, void *priv
,
143 struct wpabuf
*respData
)
148 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TLS
, respData
, &len
);
149 if (pos
== NULL
|| len
< 1) {
150 wpa_printf(MSG_INFO
, "EAP-TLS: Invalid frame");
158 static void eap_tls_process_msg(struct eap_sm
*sm
, void *priv
,
159 const struct wpabuf
*respData
)
161 struct eap_tls_data
*data
= priv
;
162 if (data
->state
== SUCCESS
&& wpabuf_len(data
->ssl
.in_buf
) == 0) {
163 wpa_printf(MSG_DEBUG
, "EAP-TLS: Client acknowledged final TLS "
164 "handshake message");
167 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0)
168 eap_tls_state(data
, FAILURE
);
172 static void eap_tls_process(struct eap_sm
*sm
, void *priv
,
173 struct wpabuf
*respData
)
175 struct eap_tls_data
*data
= priv
;
176 if (eap_server_tls_process(sm
, &data
->ssl
, respData
, data
,
177 EAP_TYPE_TLS
, NULL
, eap_tls_process_msg
) <
179 eap_tls_state(data
, FAILURE
);
183 static Boolean
eap_tls_isDone(struct eap_sm
*sm
, void *priv
)
185 struct eap_tls_data
*data
= priv
;
186 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
190 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
192 struct eap_tls_data
*data
= priv
;
195 if (data
->state
!= SUCCESS
)
198 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
199 "client EAP encryption",
202 *len
= EAP_TLS_KEY_LEN
;
203 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived key",
204 eapKeyData
, EAP_TLS_KEY_LEN
);
206 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive key");
213 static u8
* eap_tls_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
215 struct eap_tls_data
*data
= priv
;
216 u8
*eapKeyData
, *emsk
;
218 if (data
->state
!= SUCCESS
)
221 eapKeyData
= eap_server_tls_derive_key(sm
, &data
->ssl
,
222 "client EAP encryption",
223 EAP_TLS_KEY_LEN
+ EAP_EMSK_LEN
);
225 emsk
= os_malloc(EAP_EMSK_LEN
);
227 os_memcpy(emsk
, eapKeyData
+ EAP_TLS_KEY_LEN
,
235 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived EMSK",
238 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive EMSK");
245 static Boolean
eap_tls_isSuccess(struct eap_sm
*sm
, void *priv
)
247 struct eap_tls_data
*data
= priv
;
248 return data
->state
== SUCCESS
;
252 int eap_server_tls_register(void)
254 struct eap_method
*eap
;
257 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
258 EAP_VENDOR_IETF
, EAP_TYPE_TLS
, "TLS");
262 eap
->init
= eap_tls_init
;
263 eap
->reset
= eap_tls_reset
;
264 eap
->buildReq
= eap_tls_buildReq
;
265 eap
->check
= eap_tls_check
;
266 eap
->process
= eap_tls_process
;
267 eap
->isDone
= eap_tls_isDone
;
268 eap
->getKey
= eap_tls_getKey
;
269 eap
->isSuccess
= eap_tls_isSuccess
;
270 eap
->get_emsk
= eap_tls_get_emsk
;
272 ret
= eap_server_method_register(eap
);
274 eap_server_method_free(eap
);