• 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(enum eap_type type,size_t payload_len,u8 code,u8 identifier)21 struct wpabuf * eap_tls_msg_alloc(enum eap_type 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 	else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
29 		return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
30 				     EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
31 				     code, identifier);
32 	return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
33 			     identifier);
34 }
35 
36 
37 #ifdef CONFIG_TLS_INTERNAL
eap_server_tls_log_cb(void * ctx,const char * msg)38 static void eap_server_tls_log_cb(void *ctx, const char *msg)
39 {
40 	struct eap_sm *sm = ctx;
41 	eap_log_msg(sm, "TLS: %s", msg);
42 }
43 #endif /* CONFIG_TLS_INTERNAL */
44 
45 
eap_server_tls_ssl_init(struct eap_sm * sm,struct eap_ssl_data * data,int verify_peer,int eap_type)46 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
47 			    int verify_peer, int eap_type)
48 {
49 	u8 session_ctx[8];
50 	unsigned int flags = sm->cfg->tls_flags;
51 
52 	if (!sm->cfg->ssl_ctx) {
53 		wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
54 		return -1;
55 	}
56 
57 	data->eap = sm;
58 	data->phase2 = sm->init_phase2;
59 
60 	data->conn = tls_connection_init(sm->cfg->ssl_ctx);
61 	if (data->conn == NULL) {
62 		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
63 			   "connection");
64 		return -1;
65 	}
66 
67 #ifdef CONFIG_TLS_INTERNAL
68 	tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
69 #ifdef CONFIG_TESTING_OPTIONS
70 	tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
71 #endif /* CONFIG_TESTING_OPTIONS */
72 #endif /* CONFIG_TLS_INTERNAL */
73 
74 	if (eap_type != EAP_TYPE_FAST)
75 		flags |= TLS_CONN_DISABLE_SESSION_TICKET;
76 	os_memcpy(session_ctx, "hostapd", 7);
77 	session_ctx[7] = (u8) eap_type;
78 	if (tls_connection_set_verify(sm->cfg->ssl_ctx, data->conn, verify_peer,
79 				      flags, session_ctx,
80 				      sizeof(session_ctx))) {
81 		wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
82 			   "of TLS peer certificate");
83 		tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
84 		data->conn = NULL;
85 		return -1;
86 	}
87 
88 	data->tls_out_limit = sm->cfg->fragment_size > 0 ?
89 		sm->cfg->fragment_size : 1398;
90 	if (data->phase2) {
91 		/* Limit the fragment size in the inner TLS authentication
92 		 * since the outer authentication with EAP-PEAP does not yet
93 		 * support fragmentation */
94 		if (data->tls_out_limit > 100)
95 			data->tls_out_limit -= 100;
96 	}
97 	return 0;
98 }
99 
100 
eap_server_tls_ssl_deinit(struct eap_sm * sm,struct eap_ssl_data * data)101 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
102 {
103 	tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
104 	eap_server_tls_free_in_buf(data);
105 	wpabuf_free(data->tls_out);
106 	data->tls_out = NULL;
107 }
108 
109 
eap_server_tls_derive_key(struct eap_sm * sm,struct eap_ssl_data * data,const char * label,const u8 * context,size_t context_len,size_t len)110 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
111 			       const char *label, const u8 *context,
112 			       size_t context_len, size_t len)
113 {
114 	u8 *out;
115 
116 	out = os_malloc(len);
117 	if (out == NULL)
118 		return NULL;
119 
120 	if (tls_connection_export_key(sm->cfg->ssl_ctx, data->conn, label,
121 				      context, context_len, out, len)) {
122 		os_free(out);
123 		return NULL;
124 	}
125 
126 	return out;
127 }
128 
129 
130 /**
131  * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
132  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
133  * @data: Data for TLS processing
134  * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
135  * @len: Pointer to length of the session ID generated
136  * Returns: Pointer to allocated Session-Id on success or %NULL on failure
137  *
138  * This function derive the Session-Id based on the TLS session data
139  * (client/server random and method type).
140  *
141  * The caller is responsible for freeing the returned buffer.
142  */
eap_server_tls_derive_session_id(struct eap_sm * sm,struct eap_ssl_data * data,u8 eap_type,size_t * len)143 u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
144 				      struct eap_ssl_data *data, u8 eap_type,
145 				      size_t *len)
146 {
147 	struct tls_random keys;
148 	u8 *out;
149 
150 	if (data->tls_v13) {
151 		u8 *id, *method_id;
152 		const u8 context[] = { eap_type };
153 
154 		/* Session-Id = <EAP-Type> || Method-Id
155 		 * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
156 		 *                          Type-Code, 64)
157 		 */
158 		*len = 1 + 64;
159 		id = os_malloc(*len);
160 		if (!id)
161 			return NULL;
162 		method_id = eap_server_tls_derive_key(
163 			sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64);
164 		if (!method_id) {
165 			os_free(id);
166 			return NULL;
167 		}
168 		id[0] = eap_type;
169 		os_memcpy(id + 1, method_id, 64);
170 		os_free(method_id);
171 		return id;
172 	}
173 
174 	if (tls_connection_get_random(sm->cfg->ssl_ctx, data->conn, &keys))
175 		return NULL;
176 
177 	if (keys.client_random == NULL || keys.server_random == NULL)
178 		return NULL;
179 
180 	*len = 1 + keys.client_random_len + keys.server_random_len;
181 	out = os_malloc(*len);
182 	if (out == NULL)
183 		return NULL;
184 
185 	/* Session-Id = EAP type || client.random || server.random */
186 	out[0] = eap_type;
187 	os_memcpy(out + 1, keys.client_random, keys.client_random_len);
188 	os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
189 		  keys.server_random_len);
190 
191 	return out;
192 }
193 
194 
eap_server_tls_build_msg(struct eap_ssl_data * data,int eap_type,int version,u8 id)195 struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
196 					 int eap_type, int version, u8 id)
197 {
198 	struct wpabuf *req;
199 	u8 flags;
200 	size_t send_len, plen;
201 
202 	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
203 	if (data->tls_out == NULL) {
204 		wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
205 		return NULL;
206 	}
207 
208 	flags = version;
209 	send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
210 	if (1 + send_len > data->tls_out_limit) {
211 		send_len = data->tls_out_limit - 1;
212 		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
213 		if (data->tls_out_pos == 0) {
214 			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
215 			send_len -= 4;
216 		}
217 	}
218 
219 	plen = 1 + send_len;
220 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
221 		plen += 4;
222 
223 	req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
224 	if (req == NULL)
225 		return NULL;
226 
227 	wpabuf_put_u8(req, flags); /* Flags */
228 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
229 		wpabuf_put_be32(req, wpabuf_len(data->tls_out));
230 
231 	wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
232 			send_len);
233 	data->tls_out_pos += send_len;
234 
235 	if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
236 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
237 			   "(message sent completely)",
238 			   (unsigned long) send_len);
239 		wpabuf_free(data->tls_out);
240 		data->tls_out = NULL;
241 		data->tls_out_pos = 0;
242 		data->state = MSG;
243 	} else {
244 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
245 			   "(%lu more to send)", (unsigned long) send_len,
246 			   (unsigned long) wpabuf_len(data->tls_out) -
247 			   data->tls_out_pos);
248 		data->state = WAIT_FRAG_ACK;
249 	}
250 
251 	return req;
252 }
253 
254 
eap_server_tls_build_ack(u8 id,int eap_type,int version)255 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
256 {
257 	struct wpabuf *req;
258 
259 	req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
260 	if (req == NULL)
261 		return NULL;
262 	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
263 	wpabuf_put_u8(req, version); /* Flags */
264 	return req;
265 }
266 
267 
eap_server_tls_process_cont(struct eap_ssl_data * data,const u8 * buf,size_t len)268 static int eap_server_tls_process_cont(struct eap_ssl_data *data,
269 				       const u8 *buf, size_t len)
270 {
271 	/* Process continuation of a pending message */
272 	if (len > wpabuf_tailroom(data->tls_in)) {
273 		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
274 		return -1;
275 	}
276 
277 	wpabuf_put_data(data->tls_in, buf, len);
278 	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
279 		   "bytes more", (unsigned long) len,
280 		   (unsigned long) wpabuf_tailroom(data->tls_in));
281 
282 	return 0;
283 }
284 
285 
eap_server_tls_process_fragment(struct eap_ssl_data * data,u8 flags,u32 message_length,const u8 * buf,size_t len)286 static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
287 					   u8 flags, u32 message_length,
288 					   const u8 *buf, size_t len)
289 {
290 	/* Process a fragment that is not the last one of the message */
291 	if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
292 		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
293 			   "fragmented packet");
294 		return -1;
295 	}
296 
297 	if (data->tls_in == NULL) {
298 		/* First fragment of the message */
299 
300 		/* Limit length to avoid rogue peers from causing large
301 		 * memory allocations. */
302 		if (message_length > 65536) {
303 			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
304 				   " over 64 kB)");
305 			return -1;
306 		}
307 
308 		if (len > message_length) {
309 			wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
310 				   "first fragment of frame (TLS Message "
311 				   "Length %d bytes)",
312 				   (int) len, (int) message_length);
313 			return -1;
314 		}
315 
316 		data->tls_in = wpabuf_alloc(message_length);
317 		if (data->tls_in == NULL) {
318 			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
319 			return -1;
320 		}
321 		wpabuf_put_data(data->tls_in, buf, len);
322 		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
323 			   "fragment, waiting for %lu bytes more",
324 			   (unsigned long) len,
325 			   (unsigned long) wpabuf_tailroom(data->tls_in));
326 	}
327 
328 	return 0;
329 }
330 
331 
eap_server_tls_phase1(struct eap_sm * sm,struct eap_ssl_data * data)332 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
333 {
334 	char buf[20];
335 
336 	if (data->tls_out) {
337 		/* This should not happen.. */
338 		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
339 			   "processing new message");
340 		wpabuf_free(data->tls_out);
341 		WPA_ASSERT(data->tls_out == NULL);
342 	}
343 
344 	data->tls_out = tls_connection_server_handshake(sm->cfg->ssl_ctx,
345 							data->conn,
346 							data->tls_in, NULL);
347 	if (data->tls_out == NULL) {
348 		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
349 		return -1;
350 	}
351 	if (tls_connection_get_failed(sm->cfg->ssl_ctx, data->conn)) {
352 		/* TLS processing has failed - return error */
353 		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
354 			   "report error");
355 		return -1;
356 	}
357 
358 	if (tls_get_version(sm->cfg->ssl_ctx, data->conn,
359 			    buf, sizeof(buf)) == 0) {
360 		wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
361 		data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
362 	}
363 
364 	if (!sm->serial_num &&
365 	    tls_connection_established(sm->cfg->ssl_ctx, data->conn))
366 		sm->serial_num = tls_connection_peer_serial_num(
367 			sm->cfg->ssl_ctx, data->conn);
368 
369 	/*
370 	 * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
371 	 *
372 	 * We need to signal the other end that TLS negotiation is done. We
373 	 * can't send a zero-length application data message, so we send
374 	 * application data which is one byte of zero.
375 	 *
376 	 * Note this is only done for when there is no application data to be
377 	 * sent. So this is done always for EAP-TLS but notibly not for PEAP
378 	 * even on resumption.
379 	 */
380 	if (data->tls_v13 &&
381 	    tls_connection_established(sm->cfg->ssl_ctx, data->conn)) {
382 		struct wpabuf *plain, *encr;
383 
384 		switch (sm->currentMethod) {
385 		case EAP_TYPE_PEAP:
386 			break;
387 		default:
388 			if (!tls_connection_resumed(sm->cfg->ssl_ctx,
389 						    data->conn))
390 				break;
391 			/* fallthrough */
392 		case EAP_TYPE_TLS:
393 			wpa_printf(MSG_DEBUG,
394 				   "EAP-TLS: Send Commitment Message");
395 
396 			plain = wpabuf_alloc(1);
397 			if (!plain)
398 				return -1;
399 			wpabuf_put_u8(plain, 0);
400 			encr = eap_server_tls_encrypt(sm, data, plain);
401 			wpabuf_free(plain);
402 			if (!encr)
403 				return -1;
404 			if (wpabuf_resize(&data->tls_out, wpabuf_len(encr)) < 0)
405 			{
406 				wpa_printf(MSG_INFO,
407 					   "EAP-TLS: Failed to resize output buffer");
408 				wpabuf_free(encr);
409 				return -1;
410 			}
411 			wpabuf_put_buf(data->tls_out, encr);
412 			wpa_hexdump_buf(MSG_DEBUG,
413 					"EAP-TLS: Data appended to the message",
414 					encr);
415 			wpabuf_free(encr);
416 		}
417 	}
418 
419 	return 0;
420 }
421 
422 
eap_server_tls_reassemble(struct eap_ssl_data * data,u8 flags,const u8 ** pos,size_t * left)423 static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
424 				     const u8 **pos, size_t *left)
425 {
426 	unsigned int tls_msg_len = 0;
427 	const u8 *end = *pos + *left;
428 
429 	wpa_hexdump(MSG_MSGDUMP, "SSL: Received data", *pos, *left);
430 
431 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
432 		if (*left < 4) {
433 			wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
434 				   "length");
435 			return -1;
436 		}
437 		tls_msg_len = WPA_GET_BE32(*pos);
438 		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
439 			   tls_msg_len);
440 		*pos += 4;
441 		*left -= 4;
442 
443 		if (*left > tls_msg_len) {
444 			wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
445 				   "bytes) smaller than this fragment (%d "
446 				   "bytes)", (int) tls_msg_len, (int) *left);
447 			return -1;
448 		}
449 	}
450 
451 	wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
452 		   "Message Length %u", flags, tls_msg_len);
453 
454 	if (data->state == WAIT_FRAG_ACK) {
455 		if (*left != 0) {
456 			wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
457 				   "WAIT_FRAG_ACK state");
458 			return -1;
459 		}
460 		wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
461 		return 1;
462 	}
463 
464 	if (data->tls_in &&
465 	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
466 		return -1;
467 
468 	if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
469 		if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
470 						    *pos, end - *pos) < 0)
471 			return -1;
472 
473 		data->state = FRAG_ACK;
474 		return 1;
475 	}
476 
477 	if (data->state == FRAG_ACK) {
478 		wpa_printf(MSG_DEBUG, "SSL: All fragments received");
479 		data->state = MSG;
480 	}
481 
482 	if (data->tls_in == NULL) {
483 		/* Wrap unfragmented messages as wpabuf without extra copy */
484 		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
485 		data->tls_in = &data->tmpbuf;
486 	}
487 
488 	return 0;
489 }
490 
491 
eap_server_tls_free_in_buf(struct eap_ssl_data * data)492 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
493 {
494 	if (data->tls_in != &data->tmpbuf)
495 		wpabuf_free(data->tls_in);
496 	data->tls_in = NULL;
497 }
498 
499 
eap_server_tls_encrypt(struct eap_sm * sm,struct eap_ssl_data * data,const struct wpabuf * plain)500 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
501 				       struct eap_ssl_data *data,
502 				       const struct wpabuf *plain)
503 {
504 	struct wpabuf *buf;
505 
506 	buf = tls_connection_encrypt(sm->cfg->ssl_ctx, data->conn, plain);
507 	if (buf == NULL) {
508 		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
509 		return NULL;
510 	}
511 
512 	return buf;
513 }
514 
515 
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))516 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
517 			   struct wpabuf *respData, void *priv, int eap_type,
518 			   int (*proc_version)(struct eap_sm *sm, void *priv,
519 					       int peer_version),
520 			   void (*proc_msg)(struct eap_sm *sm, void *priv,
521 					    const struct wpabuf *respData))
522 {
523 	const u8 *pos;
524 	u8 flags;
525 	size_t left;
526 	int ret, res = 0;
527 
528 	if (eap_type == EAP_UNAUTH_TLS_TYPE)
529 		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
530 				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
531 				       &left);
532 	else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
533 		pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
534 				       EAP_VENDOR_WFA_UNAUTH_TLS, respData,
535 				       &left);
536 	else
537 		pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
538 				       &left);
539 	if (pos == NULL || left < 1)
540 		return 0; /* Should not happen - frame already validated */
541 	flags = *pos++;
542 	left--;
543 	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
544 		   (unsigned long) wpabuf_len(respData), flags);
545 
546 	if (proc_version &&
547 	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
548 		return -1;
549 
550 	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
551 	if (ret < 0) {
552 		res = -1;
553 		goto done;
554 	} else if (ret == 1)
555 		return 0;
556 
557 	if (proc_msg)
558 		proc_msg(sm, priv, respData);
559 
560 	if (tls_connection_get_write_alerts(sm->cfg->ssl_ctx, data->conn) > 1) {
561 		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
562 			   "TLS processing");
563 		res = -1;
564 	}
565 
566 done:
567 	eap_server_tls_free_in_buf(data);
568 
569 	return res;
570 }
571