2 * hostapd / EAP-TLS (RFC 2716)
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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 <netinet/in.h>
23 #include "eap_tls_common.h"
27 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
);
31 struct eap_ssl_data ssl
;
32 enum { START
, CONTINUE
, SUCCESS
, FAILURE
} state
;
36 static void * eap_tls_init(struct eap_sm
*sm
)
38 struct eap_tls_data
*data
;
40 data
= malloc(sizeof(*data
));
43 memset(data
, 0, sizeof(*data
));
46 if (eap_tls_ssl_init(sm
, &data
->ssl
, 1)) {
47 wpa_printf(MSG_INFO
, "EAP-TLS: Failed to initialize SSL.");
48 eap_tls_reset(sm
, data
);
56 static void eap_tls_reset(struct eap_sm
*sm
, void *priv
)
58 struct eap_tls_data
*data
= priv
;
61 eap_tls_ssl_deinit(sm
, &data
->ssl
);
66 static u8
* eap_tls_build_start(struct eap_sm
*sm
, struct eap_tls_data
*data
,
67 int id
, size_t *reqDataLen
)
72 *reqDataLen
= sizeof(*req
) + 2;
73 req
= malloc(*reqDataLen
);
75 wpa_printf(MSG_ERROR
, "EAP-TLS: Failed to allocate memory for "
77 data
->state
= FAILURE
;
81 req
->code
= EAP_CODE_REQUEST
;
83 req
->length
= htons(*reqDataLen
);
84 pos
= (u8
*) (req
+ 1);
85 *pos
++ = EAP_TYPE_TLS
;
86 *pos
= EAP_TLS_FLAGS_START
;
88 data
->state
= CONTINUE
;
94 static u8
* eap_tls_build_req(struct eap_sm
*sm
, struct eap_tls_data
*data
,
95 int id
, size_t *reqDataLen
)
100 res
= eap_tls_buildReq_helper(sm
, &data
->ssl
, EAP_TYPE_TLS
, 0, id
,
103 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
104 wpa_printf(MSG_DEBUG
, "EAP-TLS: Done");
105 data
->state
= SUCCESS
;
109 return eap_tls_build_ack(reqDataLen
, id
, EAP_TYPE_TLS
, 0);
114 static u8
* eap_tls_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
117 struct eap_tls_data
*data
= priv
;
119 switch (data
->state
) {
121 return eap_tls_build_start(sm
, data
, id
, reqDataLen
);
123 return eap_tls_build_req(sm
, data
, id
, reqDataLen
);
125 wpa_printf(MSG_DEBUG
, "EAP-TLS: %s - unexpected state %d",
126 __func__
, data
->state
);
132 static Boolean
eap_tls_check(struct eap_sm
*sm
, void *priv
,
133 u8
*respData
, size_t respDataLen
)
135 struct eap_hdr
*resp
;
139 resp
= (struct eap_hdr
*) respData
;
140 pos
= (u8
*) (resp
+ 1);
141 if (respDataLen
< sizeof(*resp
) + 2 || *pos
!= EAP_TYPE_TLS
||
142 (len
= ntohs(resp
->length
)) > respDataLen
) {
143 wpa_printf(MSG_INFO
, "EAP-TLS: Invalid frame");
151 static void eap_tls_process(struct eap_sm
*sm
, void *priv
,
152 u8
*respData
, size_t respDataLen
)
154 struct eap_tls_data
*data
= priv
;
155 struct eap_hdr
*resp
;
158 unsigned int tls_msg_len
;
160 resp
= (struct eap_hdr
*) respData
;
161 pos
= (u8
*) (resp
+ 1);
164 left
= htons(resp
->length
) - sizeof(struct eap_hdr
) - 2;
165 wpa_printf(MSG_DEBUG
, "EAP-TLS: Received packet(len=%lu) - "
166 "Flags 0x%02x", (unsigned long) respDataLen
, flags
);
167 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
169 wpa_printf(MSG_INFO
, "EAP-TLS: Short frame with TLS "
171 data
->state
= FAILURE
;
174 tls_msg_len
= (pos
[0] << 24) | (pos
[1] << 16) | (pos
[2] << 8) |
176 wpa_printf(MSG_DEBUG
, "EAP-TLS: TLS Message Length: %d",
178 if (data
->ssl
.tls_in_left
== 0) {
179 data
->ssl
.tls_in_total
= tls_msg_len
;
180 data
->ssl
.tls_in_left
= tls_msg_len
;
181 free(data
->ssl
.tls_in
);
182 data
->ssl
.tls_in
= NULL
;
183 data
->ssl
.tls_in_len
= 0;
189 if (eap_tls_process_helper(sm
, &data
->ssl
, pos
, left
) < 0) {
190 wpa_printf(MSG_INFO
, "EAP-TLS: TLS processing failed");
191 data
->state
= FAILURE
;
195 if (tls_connection_get_write_alerts(sm
->ssl_ctx
, data
->ssl
.conn
) > 1) {
196 wpa_printf(MSG_INFO
, "EAP-TLS: Locally detected fatal error "
197 "in TLS processing");
198 data
->state
= FAILURE
;
204 static Boolean
eap_tls_isDone(struct eap_sm
*sm
, void *priv
)
206 struct eap_tls_data
*data
= priv
;
207 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
211 static u8
* eap_tls_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
213 struct eap_tls_data
*data
= priv
;
216 if (data
->state
!= SUCCESS
)
219 eapKeyData
= eap_tls_derive_key(sm
, &data
->ssl
,
220 "client EAP encryption",
223 *len
= EAP_TLS_KEY_LEN
;
224 wpa_hexdump(MSG_DEBUG
, "EAP-TLS: Derived key",
225 eapKeyData
, EAP_TLS_KEY_LEN
);
227 wpa_printf(MSG_DEBUG
, "EAP-TLS: Failed to derive key");
234 static Boolean
eap_tls_isSuccess(struct eap_sm
*sm
, void *priv
)
236 struct eap_tls_data
*data
= priv
;
237 return data
->state
== SUCCESS
;
241 const struct eap_method eap_method_tls
=
243 .method
= EAP_TYPE_TLS
,
245 .init
= eap_tls_init
,
246 .reset
= eap_tls_reset
,
247 .buildReq
= eap_tls_buildReq
,
248 .check
= eap_tls_check
,
249 .process
= eap_tls_process
,
250 .isDone
= eap_tls_isDone
,
251 .getKey
= eap_tls_getKey
,
252 .isSuccess
= eap_tls_isSuccess
,