Home | History | Annotate | Download | only in eap_server
      1 /*
      2  * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
      3  * Copyright (c) 2004-2008, Jouni Malinen <j (at) w1.fi>
      4  *
      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.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "eap_i.h"
     19 #include "eap_tls_common.h"
     20 #include "sha1.h"
     21 #include "tls.h"
     22 
     23 
     24 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
     25 			    int verify_peer)
     26 {
     27 	data->eap = sm;
     28 	data->phase2 = sm->init_phase2;
     29 
     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 "
     33 			   "connection");
     34 		return -1;
     35 	}
     36 
     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);
     41 		data->conn = NULL;
     42 		return -1;
     43 	}
     44 
     45 	/* TODO: make this configurable */
     46 	data->tls_out_limit = 1398;
     47 	if (data->phase2) {
     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;
     53 	}
     54 	return 0;
     55 }
     56 
     57 
     58 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
     59 {
     60 	tls_connection_deinit(sm->ssl_ctx, data->conn);
     61 	os_free(data->in_buf);
     62 	os_free(data->out_buf);
     63 }
     64 
     65 
     66 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
     67 			       char *label, size_t len)
     68 {
     69 	struct tls_keys keys;
     70 	u8 *rnd = NULL, *out;
     71 
     72 	out = os_malloc(len);
     73 	if (out == NULL)
     74 		return NULL;
     75 
     76 	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
     77 	    0)
     78 		return out;
     79 
     80 	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
     81 		goto fail;
     82 
     83 	if (keys.client_random == NULL || keys.server_random == NULL ||
     84 	    keys.master_key == NULL)
     85 		goto fail;
     86 
     87 	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
     88 	if (rnd == NULL)
     89 		goto fail;
     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);
     93 
     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))
     97 		goto fail;
     98 
     99 	os_free(rnd);
    100 	return out;
    101 
    102 fail:
    103 	os_free(out);
    104 	os_free(rnd);
    105 	return NULL;
    106 }
    107 
    108 
    109 struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
    110 					 int eap_type, int version, u8 id)
    111 {
    112 	struct wpabuf *req;
    113 	u8 flags;
    114 	size_t send_len, plen;
    115 
    116 	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
    117 	if (data->out_buf == NULL) {
    118 		wpa_printf(MSG_ERROR, "SSL: out_buf NULL in %s", __func__);
    119 		return NULL;
    120 	}
    121 
    122 	flags = version;
    123 	send_len = wpabuf_len(data->out_buf) - data->out_used;
    124 	if (1 + send_len > data->tls_out_limit) {
    125 		send_len = data->tls_out_limit - 1;
    126 		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
    127 		if (data->out_used == 0) {
    128 			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
    129 			send_len -= 4;
    130 		}
    131 	}
    132 
    133 	plen = 1 + send_len;
    134 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
    135 		plen += 4;
    136 
    137 	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen,
    138 			    EAP_CODE_REQUEST, id);
    139 	if (req == NULL)
    140 		return NULL;
    141 
    142 	wpabuf_put_u8(req, flags); /* Flags */
    143 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
    144 		wpabuf_put_be32(req, wpabuf_len(data->out_buf));
    145 
    146 	wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
    147 			send_len);
    148 	data->out_used += send_len;
    149 
    150 	if (data->out_used == wpabuf_len(data->out_buf)) {
    151 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
    152 			   "(message sent completely)",
    153 			   (unsigned long) send_len);
    154 		wpabuf_free(data->out_buf);
    155 		data->out_buf = NULL;
    156 		data->out_used = 0;
    157 		data->state = MSG;
    158 	} else {
    159 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
    160 			   "(%lu more to send)", (unsigned long) send_len,
    161 			   (unsigned long) wpabuf_len(data->out_buf) -
    162 			   data->out_used);
    163 		data->state = WAIT_FRAG_ACK;
    164 	}
    165 
    166 	return req;
    167 }
    168 
    169 
    170 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
    171 {
    172 	struct wpabuf *req;
    173 
    174 	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
    175 			    id);
    176 	if (req == NULL)
    177 		return NULL;
    178 	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
    179 	wpabuf_put_u8(req, version); /* Flags */
    180 	return req;
    181 }
    182 
    183 
    184 static int eap_server_tls_process_cont(struct eap_ssl_data *data,
    185 				       const u8 *buf, size_t len)
    186 {
    187 	/* Process continuation of a pending message */
    188 	if (len > wpabuf_tailroom(data->in_buf)) {
    189 		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
    190 		return -1;
    191 	}
    192 
    193 	wpabuf_put_data(data->in_buf, buf, len);
    194 	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
    195 		   "bytes more", (unsigned long) len,
    196 		   (unsigned long) wpabuf_tailroom(data->in_buf));
    197 
    198 	return 0;
    199 }
    200 
    201 
    202 static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
    203 					   u8 flags, u32 message_length,
    204 					   const u8 *buf, size_t len)
    205 {
    206 	/* Process a fragment that is not the last one of the message */
    207 	if (data->in_buf == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
    208 		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
    209 			   "fragmented packet");
    210 		return -1;
    211 	}
    212 
    213 	if (data->in_buf == NULL) {
    214 		/* First fragment of the message */
    215 
    216 		/* Limit length to avoid rogue peers from causing large
    217 		 * memory allocations. */
    218 		if (message_length > 65536) {
    219 			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
    220 				   " over 64 kB)");
    221 			return -1;
    222 		}
    223 
    224 		data->in_buf = wpabuf_alloc(message_length);
    225 		if (data->in_buf == NULL) {
    226 			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
    227 			return -1;
    228 		}
    229 		wpabuf_put_data(data->in_buf, buf, len);
    230 		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
    231 			   "fragment, waiting for %lu bytes more",
    232 			   (unsigned long) len,
    233 			   (unsigned long) wpabuf_tailroom(data->in_buf));
    234 	}
    235 
    236 	return 0;
    237 }
    238 
    239 
    240 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
    241 {
    242 	u8 *next;
    243 	size_t next_len;
    244 
    245 	next = tls_connection_server_handshake(
    246 		sm->ssl_ctx, data->conn,
    247 		wpabuf_mhead(data->in_buf),
    248 		wpabuf_len(data->in_buf),
    249 		&next_len);
    250 	if (next == NULL) {
    251 		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
    252 		return -1;
    253 	}
    254 	if (data->out_buf) {
    255 		/* This should not happen.. */
    256 		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
    257 			   "processing new message");
    258 		os_free(data->out_buf);
    259 		WPA_ASSERT(data->out_buf == NULL);
    260 	}
    261 	data->out_buf = wpabuf_alloc_ext_data(next, next_len);
    262 	if (data->out_buf == NULL) {
    263 		os_free(next);
    264 		return -1;
    265 	}
    266 	return 0;
    267 }
    268 
    269 
    270 static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
    271 				     const u8 **pos, size_t *left)
    272 {
    273 	unsigned int tls_msg_len = 0;
    274 	const u8 *end = *pos + *left;
    275 
    276 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
    277 		if (*left < 4) {
    278 			wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
    279 				   "length");
    280 			return -1;
    281 		}
    282 		tls_msg_len = WPA_GET_BE32(*pos);
    283 		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
    284 			   tls_msg_len);
    285 		*pos += 4;
    286 		*left -= 4;
    287 	}
    288 
    289 	wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
    290 		   "Message Length %u", flags, tls_msg_len);
    291 
    292 	if (data->state == WAIT_FRAG_ACK) {
    293 		if (*left != 0) {
    294 			wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
    295 				   "WAIT_FRAG_ACK state");
    296 			return -1;
    297 		}
    298 		wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
    299 		return 1;
    300 	}
    301 
    302 	if (data->in_buf &&
    303 	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
    304 		return -1;
    305 
    306 	if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
    307 		if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
    308 						    *pos, end - *pos) < 0)
    309 			return -1;
    310 
    311 		data->state = FRAG_ACK;
    312 		return 1;
    313 	}
    314 
    315 	if (data->state == FRAG_ACK) {
    316 		wpa_printf(MSG_DEBUG, "SSL: All fragments received");
    317 		data->state = MSG;
    318 	}
    319 
    320 	if (data->in_buf == NULL) {
    321 		/* Wrap unfragmented messages as wpabuf without extra copy */
    322 		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
    323 		data->in_buf = &data->tmpbuf;
    324 	}
    325 
    326 	return 0;
    327 }
    328 
    329 
    330 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
    331 {
    332 	if (data->in_buf != &data->tmpbuf)
    333 		wpabuf_free(data->in_buf);
    334 	data->in_buf = NULL;
    335 }
    336 
    337 
    338 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
    339 				       struct eap_ssl_data *data,
    340 				       const u8 *plain, size_t plain_len)
    341 {
    342 	int res;
    343 	struct wpabuf *buf;
    344 	size_t buf_len;
    345 
    346 	/* reserve some extra room for encryption overhead */
    347 	buf_len = plain_len + 300;
    348 	buf = wpabuf_alloc(buf_len);
    349 	if (buf == NULL)
    350 		return NULL;
    351 	res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
    352 				     plain, plain_len, wpabuf_put(buf, 0),
    353 				     buf_len);
    354 	if (res < 0) {
    355 		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
    356 		wpabuf_free(buf);
    357 		return NULL;
    358 	}
    359 
    360 	wpabuf_put(buf, res);
    361 
    362 	return buf;
    363 }
    364 
    365 
    366 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
    367 			   struct wpabuf *respData, void *priv, int eap_type,
    368 			   int (*proc_version)(struct eap_sm *sm, void *priv,
    369 					       int peer_version),
    370 			   void (*proc_msg)(struct eap_sm *sm, void *priv,
    371 					    const struct wpabuf *respData))
    372 {
    373 	const u8 *pos;
    374 	u8 flags;
    375 	size_t left;
    376 	int ret, res = 0;
    377 
    378 	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left);
    379 	if (pos == NULL || left < 1)
    380 		return 0; /* Should not happen - frame already validated */
    381 	flags = *pos++;
    382 	left--;
    383 	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
    384 		   (unsigned long) wpabuf_len(respData), flags);
    385 
    386 	if (proc_version &&
    387 	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
    388 		return -1;
    389 
    390 	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
    391 	if (ret < 0) {
    392 		res = -1;
    393 		goto done;
    394 	} else if (ret == 1)
    395 		return 0;
    396 
    397 	if (proc_msg)
    398 		proc_msg(sm, priv, respData);
    399 
    400 	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
    401 		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
    402 			   "TLS processing");
    403 		res = -1;
    404 	}
    405 
    406 done:
    407 	eap_server_tls_free_in_buf(data);
    408 
    409 	return res;
    410 }
    411