2 * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
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"
24 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
28 data->phase2 = sm->init_phase2;
30 data->conn = tls_connection_init(sm->ssl_ctx);
31 if (data->conn == NULL) {
32 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
37 if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
38 wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
39 "of TLS peer certificate");
40 tls_connection_deinit(sm->ssl_ctx, data->conn);
45 /* TODO: make this configurable */
46 data->tls_out_limit = 1398;
48 /* Limit the fragment size in the inner TLS authentication
49 * since the outer authentication with EAP-PEAP does not yet
50 * support fragmentation */
51 if (data->tls_out_limit > 100)
52 data->tls_out_limit -= 100;
58 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
60 tls_connection_deinit(sm->ssl_ctx, data->conn);
61 os_free(data->in_buf);
62 os_free(data->out_buf);
66 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
67 char *label, size_t len)
76 if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
80 if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
83 if (keys.client_random == NULL || keys.server_random == NULL ||
84 keys.master_key == NULL)
87 rnd = os_malloc(keys.client_random_len + keys.server_random_len);
90 os_memcpy(rnd, keys.client_random, keys.client_random_len);
91 os_memcpy(rnd + keys.client_random_len, keys.server_random,
92 keys.server_random_len);
94 if (tls_prf(keys.master_key, keys.master_key_len,
95 label, rnd, keys.client_random_len +
96 keys.server_random_len, out, len))
109 struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
110 int eap_type, int version, u8 id)
114 size_t send_len, plen;
116 wpa_printf(MSG_DEBUG, "SSL: Generating Request");
119 send_len = wpabuf_len(data->out_buf) - data->out_used;
120 if (1 + send_len > data->tls_out_limit) {
121 send_len = data->tls_out_limit - 1;
122 flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
123 if (data->out_used == 0) {
124 flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
130 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
133 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen,
134 EAP_CODE_REQUEST, id);
138 wpabuf_put_u8(req, flags); /* Flags */
139 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
140 wpabuf_put_be32(req, wpabuf_len(data->out_buf));
142 wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
144 data->out_used += send_len;
146 if (data->out_used == wpabuf_len(data->out_buf)) {
147 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
148 "(message sent completely)",
149 (unsigned long) send_len);
150 wpabuf_free(data->out_buf);
151 data->out_buf = NULL;
155 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
156 "(%lu more to send)", (unsigned long) send_len,
157 (unsigned long) wpabuf_len(data->out_buf) -
159 data->state = WAIT_FRAG_ACK;
166 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
170 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
174 wpa_printf(MSG_DEBUG, "SSL: Building ACK");
175 wpabuf_put_u8(req, version); /* Flags */
180 static int eap_server_tls_process_cont(struct eap_ssl_data *data,
181 const u8 *buf, size_t len)
183 /* Process continuation of a pending message */
184 if (len > wpabuf_tailroom(data->in_buf)) {
185 wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
189 wpabuf_put_data(data->in_buf, buf, len);
190 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
191 "bytes more", (unsigned long) len,
192 (unsigned long) wpabuf_tailroom(data->in_buf));
198 static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
199 u8 flags, u32 message_length,
200 const u8 *buf, size_t len)
202 /* Process a fragment that is not the last one of the message */
203 if (data->in_buf == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
204 wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
205 "fragmented packet");
209 if (data->in_buf == NULL) {
210 /* First fragment of the message */
212 /* Limit length to avoid rogue peers from causing large
213 * memory allocations. */
214 if (message_length > 65536) {
215 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
220 data->in_buf = wpabuf_alloc(message_length);
221 if (data->in_buf == NULL) {
222 wpa_printf(MSG_DEBUG, "SSL: No memory for message");
225 wpabuf_put_data(data->in_buf, buf, len);
226 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
227 "fragment, waiting for %lu bytes more",
229 (unsigned long) wpabuf_tailroom(data->in_buf));
236 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
241 next = tls_connection_server_handshake(
242 sm->ssl_ctx, data->conn,
243 wpabuf_mhead(data->in_buf),
244 wpabuf_len(data->in_buf),
247 wpa_printf(MSG_INFO, "SSL: TLS processing failed");
251 /* This should not happen.. */
252 wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
253 "processing new message");
254 os_free(data->out_buf);
255 WPA_ASSERT(data->out_buf == NULL);
257 data->out_buf = wpabuf_alloc_ext_data(next, next_len);
258 if (data->out_buf == NULL) {
266 int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
267 const u8 **pos, size_t *left)
269 unsigned int tls_msg_len = 0;
270 const u8 *end = *pos + *left;
272 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
274 wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
278 tls_msg_len = WPA_GET_BE32(*pos);
279 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
285 wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
286 "Message Length %u", flags, tls_msg_len);
288 if (data->state == WAIT_FRAG_ACK) {
290 wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
291 "WAIT_FRAG_ACK state");
294 wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
299 eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
302 if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
303 if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
304 *pos, end - *pos) < 0)
307 data->state = FRAG_ACK;
311 if (data->state == FRAG_ACK) {
312 wpa_printf(MSG_DEBUG, "SSL: All fragments received");
316 if (data->in_buf == NULL) {
317 /* Wrap unfragmented messages as wpabuf without extra copy */
318 wpabuf_set(&data->tmpbuf, *pos, end - *pos);
319 data->in_buf = &data->tmpbuf;
326 void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
328 if (data->in_buf != &data->tmpbuf)
329 wpabuf_free(data->in_buf);
334 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
335 struct eap_ssl_data *data,
336 const u8 *plain, size_t plain_len)
342 /* reserve some extra room for encryption overhead */
343 buf_len = plain_len + 200;
344 buf = wpabuf_alloc(buf_len);
345 res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
346 plain, plain_len, wpabuf_put(buf, 0),
349 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
354 wpabuf_put(buf, res);