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