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