1 /*
2  * SSL/TLS interface functions for GnuTLS
3  * Copyright (c) 2004-2011, 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 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
12 #ifdef PKCS12_FUNCS
13 #include <gnutls/pkcs12.h>
14 #endif /* PKCS12_FUNCS */
15 #if GNUTLS_VERSION_NUMBER >= 0x030103
16 #include <gnutls/ocsp.h>
17 #endif /* 3.1.3 */
18 
19 #include "common.h"
20 #include "crypto/crypto.h"
21 #include "tls.h"
22 
23 
24 static int tls_gnutls_ref_count = 0;
25 
26 struct tls_global {
27 	/* Data for session resumption */
28 	void *session_data;
29 	size_t session_data_size;
30 
31 	int server;
32 
33 	int params_set;
34 	gnutls_certificate_credentials_t xcred;
35 
36 	void (*event_cb)(void *ctx, enum tls_event ev,
37 			 union tls_event_data *data);
38 	void *cb_ctx;
39 	int cert_in_cb;
40 
41 	char *ocsp_stapling_response;
42 };
43 
44 struct tls_connection {
45 	struct tls_global *global;
46 	gnutls_session_t session;
47 	int read_alerts, write_alerts, failed;
48 
49 	u8 *pre_shared_secret;
50 	size_t pre_shared_secret_len;
51 	int established;
52 	int verify_peer;
53 	unsigned int disable_time_checks:1;
54 
55 	struct wpabuf *push_buf;
56 	struct wpabuf *pull_buf;
57 	const u8 *pull_buf_offset;
58 
59 	int params_set;
60 	gnutls_certificate_credentials_t xcred;
61 
62 	char *suffix_match;
63 	char *domain_match;
64 	unsigned int flags;
65 };
66 
67 
68 static int tls_connection_verify_peer(gnutls_session_t session);
69 
70 
tls_log_func(int level,const char * msg)71 static void tls_log_func(int level, const char *msg)
72 {
73 	char *s, *pos;
74 	if (level == 6 || level == 7) {
75 		/* These levels seem to be mostly I/O debug and msg dumps */
76 		return;
77 	}
78 
79 	s = os_strdup(msg);
80 	if (s == NULL)
81 		return;
82 
83 	pos = s;
84 	while (*pos != '\0') {
85 		if (*pos == '\n') {
86 			*pos = '\0';
87 			break;
88 		}
89 		pos++;
90 	}
91 	wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
92 		   "gnutls<%d> %s", level, s);
93 	os_free(s);
94 }
95 
96 
tls_init(const struct tls_config * conf)97 void * tls_init(const struct tls_config *conf)
98 {
99 	struct tls_global *global;
100 
101 	if (tls_gnutls_ref_count == 0) {
102 		wpa_printf(MSG_DEBUG,
103 			   "GnuTLS: Library version %s (runtime) - %s (build)",
104 			   gnutls_check_version(NULL), GNUTLS_VERSION);
105 	}
106 
107 	global = os_zalloc(sizeof(*global));
108 	if (global == NULL)
109 		return NULL;
110 
111 	if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
112 		os_free(global);
113 		return NULL;
114 	}
115 	tls_gnutls_ref_count++;
116 
117 	gnutls_global_set_log_function(tls_log_func);
118 	if (wpa_debug_show_keys)
119 		gnutls_global_set_log_level(11);
120 
121 	if (conf) {
122 		global->event_cb = conf->event_cb;
123 		global->cb_ctx = conf->cb_ctx;
124 		global->cert_in_cb = conf->cert_in_cb;
125 	}
126 
127 	return global;
128 }
129 
130 
tls_deinit(void * ssl_ctx)131 void tls_deinit(void *ssl_ctx)
132 {
133 	struct tls_global *global = ssl_ctx;
134 	if (global) {
135 		if (global->params_set)
136 			gnutls_certificate_free_credentials(global->xcred);
137 		os_free(global->session_data);
138 		os_free(global->ocsp_stapling_response);
139 		os_free(global);
140 	}
141 
142 	tls_gnutls_ref_count--;
143 	if (tls_gnutls_ref_count == 0)
144 		gnutls_global_deinit();
145 }
146 
147 
tls_get_errors(void * ssl_ctx)148 int tls_get_errors(void *ssl_ctx)
149 {
150 	return 0;
151 }
152 
153 
tls_pull_func(gnutls_transport_ptr_t ptr,void * buf,size_t len)154 static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
155 			     size_t len)
156 {
157 	struct tls_connection *conn = (struct tls_connection *) ptr;
158 	const u8 *end;
159 	if (conn->pull_buf == NULL) {
160 		errno = EWOULDBLOCK;
161 		return -1;
162 	}
163 
164 	end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
165 	if ((size_t) (end - conn->pull_buf_offset) < len)
166 		len = end - conn->pull_buf_offset;
167 	os_memcpy(buf, conn->pull_buf_offset, len);
168 	conn->pull_buf_offset += len;
169 	if (conn->pull_buf_offset == end) {
170 		wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
171 		wpabuf_free(conn->pull_buf);
172 		conn->pull_buf = NULL;
173 		conn->pull_buf_offset = NULL;
174 	} else {
175 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
176 			   __func__,
177 			   (unsigned long) (end - conn->pull_buf_offset));
178 	}
179 	return len;
180 }
181 
182 
tls_push_func(gnutls_transport_ptr_t ptr,const void * buf,size_t len)183 static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
184 			     size_t len)
185 {
186 	struct tls_connection *conn = (struct tls_connection *) ptr;
187 
188 	if (wpabuf_resize(&conn->push_buf, len) < 0) {
189 		errno = ENOMEM;
190 		return -1;
191 	}
192 	wpabuf_put_data(conn->push_buf, buf, len);
193 
194 	return len;
195 }
196 
197 
tls_gnutls_init_session(struct tls_global * global,struct tls_connection * conn)198 static int tls_gnutls_init_session(struct tls_global *global,
199 				   struct tls_connection *conn)
200 {
201 	const char *err;
202 	int ret;
203 
204 	ret = gnutls_init(&conn->session,
205 			  global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
206 	if (ret < 0) {
207 		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
208 			   "connection: %s", gnutls_strerror(ret));
209 		return -1;
210 	}
211 
212 	ret = gnutls_set_default_priority(conn->session);
213 	if (ret < 0)
214 		goto fail;
215 
216 	ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
217 					 &err);
218 	if (ret < 0) {
219 		wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
220 			   "'%s'", err);
221 		goto fail;
222 	}
223 
224 	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
225 	gnutls_transport_set_push_function(conn->session, tls_push_func);
226 	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
227 	gnutls_session_set_ptr(conn->session, conn);
228 
229 	return 0;
230 
231 fail:
232 	wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
233 		   gnutls_strerror(ret));
234 	gnutls_deinit(conn->session);
235 	return -1;
236 }
237 
238 
tls_connection_init(void * ssl_ctx)239 struct tls_connection * tls_connection_init(void *ssl_ctx)
240 {
241 	struct tls_global *global = ssl_ctx;
242 	struct tls_connection *conn;
243 	int ret;
244 
245 	conn = os_zalloc(sizeof(*conn));
246 	if (conn == NULL)
247 		return NULL;
248 	conn->global = global;
249 
250 	if (tls_gnutls_init_session(global, conn)) {
251 		os_free(conn);
252 		return NULL;
253 	}
254 
255 	if (global->params_set) {
256 		ret = gnutls_credentials_set(conn->session,
257 					     GNUTLS_CRD_CERTIFICATE,
258 					     global->xcred);
259 		if (ret < 0) {
260 			wpa_printf(MSG_INFO, "Failed to configure "
261 				   "credentials: %s", gnutls_strerror(ret));
262 			os_free(conn);
263 			return NULL;
264 		}
265 	}
266 
267 	if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
268 		os_free(conn);
269 		return NULL;
270 	}
271 
272 	return conn;
273 }
274 
275 
tls_connection_deinit(void * ssl_ctx,struct tls_connection * conn)276 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
277 {
278 	if (conn == NULL)
279 		return;
280 
281 	gnutls_certificate_free_credentials(conn->xcred);
282 	gnutls_deinit(conn->session);
283 	os_free(conn->pre_shared_secret);
284 	wpabuf_free(conn->push_buf);
285 	wpabuf_free(conn->pull_buf);
286 	os_free(conn->suffix_match);
287 	os_free(conn->domain_match);
288 	os_free(conn);
289 }
290 
291 
tls_connection_established(void * ssl_ctx,struct tls_connection * conn)292 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
293 {
294 	return conn ? conn->established : 0;
295 }
296 
297 
tls_connection_shutdown(void * ssl_ctx,struct tls_connection * conn)298 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
299 {
300 	struct tls_global *global = ssl_ctx;
301 	int ret;
302 
303 	if (conn == NULL)
304 		return -1;
305 
306 	/* Shutdown previous TLS connection without notifying the peer
307 	 * because the connection was already terminated in practice
308 	 * and "close notify" shutdown alert would confuse AS. */
309 	gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
310 	wpabuf_free(conn->push_buf);
311 	conn->push_buf = NULL;
312 	conn->established = 0;
313 
314 	gnutls_deinit(conn->session);
315 	if (tls_gnutls_init_session(global, conn)) {
316 		wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
317 			   "for session resumption use");
318 		return -1;
319 	}
320 
321 	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
322 				     conn->params_set ? conn->xcred :
323 				     global->xcred);
324 	if (ret < 0) {
325 		wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
326 			   "for session resumption: %s", gnutls_strerror(ret));
327 		return -1;
328 	}
329 
330 	if (global->session_data) {
331 		ret = gnutls_session_set_data(conn->session,
332 					      global->session_data,
333 					      global->session_data_size);
334 		if (ret < 0) {
335 			wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
336 				   "data: %s", gnutls_strerror(ret));
337 			return -1;
338 		}
339 	}
340 
341 	return 0;
342 }
343 
344 
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)345 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
346 			      const struct tls_connection_params *params)
347 {
348 	int ret;
349 
350 	if (conn == NULL || params == NULL)
351 		return -1;
352 
353 	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
354 		wpa_printf(MSG_INFO,
355 			   "GnuTLS: ocsp=3 not supported");
356 		return -1;
357 	}
358 
359 	if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
360 		wpa_printf(MSG_INFO,
361 			   "GnuTLS: tls_ext_cert_check=1 not supported");
362 		return -1;
363 	}
364 
365 	if (params->subject_match) {
366 		wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
367 		return -1;
368 	}
369 
370 	if (params->altsubject_match) {
371 		wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
372 		return -1;
373 	}
374 
375 	os_free(conn->suffix_match);
376 	conn->suffix_match = NULL;
377 	if (params->suffix_match) {
378 		conn->suffix_match = os_strdup(params->suffix_match);
379 		if (conn->suffix_match == NULL)
380 			return -1;
381 	}
382 
383 #if GNUTLS_VERSION_NUMBER >= 0x030300
384 	os_free(conn->domain_match);
385 	conn->domain_match = NULL;
386 	if (params->domain_match) {
387 		conn->domain_match = os_strdup(params->domain_match);
388 		if (conn->domain_match == NULL)
389 			return -1;
390 	}
391 #else /* < 3.3.0 */
392 	if (params->domain_match) {
393 		wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
394 		return -1;
395 	}
396 #endif /* >= 3.3.0 */
397 
398 	conn->flags = params->flags;
399 
400 	if (params->openssl_ciphers) {
401 		wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
402 		return -1;
403 	}
404 
405 	/* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
406 	 * to force peer validation(?) */
407 
408 	if (params->ca_cert) {
409 		wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
410 			   params->ca_cert);
411 		ret = gnutls_certificate_set_x509_trust_file(
412 			conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
413 		if (ret < 0) {
414 			wpa_printf(MSG_DEBUG,
415 				   "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
416 				   params->ca_cert,
417 				   gnutls_strerror(ret));
418 			ret = gnutls_certificate_set_x509_trust_file(
419 				conn->xcred, params->ca_cert,
420 				GNUTLS_X509_FMT_PEM);
421 			if (ret < 0) {
422 				wpa_printf(MSG_DEBUG,
423 					   "Failed to read CA cert '%s' in PEM format: %s",
424 					   params->ca_cert,
425 					   gnutls_strerror(ret));
426 				return -1;
427 			}
428 		}
429 	} else if (params->ca_cert_blob) {
430 		gnutls_datum_t ca;
431 
432 		ca.data = (unsigned char *) params->ca_cert_blob;
433 		ca.size = params->ca_cert_blob_len;
434 
435 		ret = gnutls_certificate_set_x509_trust_mem(
436 			conn->xcred, &ca, GNUTLS_X509_FMT_DER);
437 		if (ret < 0) {
438 			wpa_printf(MSG_DEBUG,
439 				   "Failed to parse CA cert in DER format: %s",
440 				   gnutls_strerror(ret));
441 			ret = gnutls_certificate_set_x509_trust_mem(
442 				conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
443 			if (ret < 0) {
444 				wpa_printf(MSG_DEBUG,
445 					   "Failed to parse CA cert in PEM format: %s",
446 					   gnutls_strerror(ret));
447 				return -1;
448 			}
449 		}
450 	} else if (params->ca_path) {
451 		wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
452 		return -1;
453 	}
454 
455 	conn->disable_time_checks = 0;
456 	if (params->ca_cert || params->ca_cert_blob) {
457 		conn->verify_peer = 1;
458 		gnutls_certificate_set_verify_function(
459 			conn->xcred, tls_connection_verify_peer);
460 
461 		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
462 			gnutls_certificate_set_verify_flags(
463 				conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
464 		}
465 
466 		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
467 			conn->disable_time_checks = 1;
468 			gnutls_certificate_set_verify_flags(
469 				conn->xcred,
470 				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
471 		}
472 	}
473 
474 	if (params->client_cert && params->private_key) {
475 #if GNUTLS_VERSION_NUMBER >= 0x03010b
476 		ret = gnutls_certificate_set_x509_key_file2(
477 			conn->xcred, params->client_cert, params->private_key,
478 			GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
479 #else
480 		/* private_key_passwd not (easily) supported here */
481 		ret = gnutls_certificate_set_x509_key_file(
482 			conn->xcred, params->client_cert, params->private_key,
483 			GNUTLS_X509_FMT_DER);
484 #endif
485 		if (ret < 0) {
486 			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
487 				   "in DER format: %s", gnutls_strerror(ret));
488 #if GNUTLS_VERSION_NUMBER >= 0x03010b
489 			ret = gnutls_certificate_set_x509_key_file2(
490 				conn->xcred, params->client_cert,
491 				params->private_key, GNUTLS_X509_FMT_PEM,
492 				params->private_key_passwd, 0);
493 #else
494 			ret = gnutls_certificate_set_x509_key_file(
495 				conn->xcred, params->client_cert,
496 				params->private_key, GNUTLS_X509_FMT_PEM);
497 #endif
498 			if (ret < 0) {
499 				wpa_printf(MSG_DEBUG, "Failed to read client "
500 					   "cert/key in PEM format: %s",
501 					   gnutls_strerror(ret));
502 				return ret;
503 			}
504 		}
505 	} else if (params->private_key) {
506 		int pkcs12_ok = 0;
507 #ifdef PKCS12_FUNCS
508 		/* Try to load in PKCS#12 format */
509 		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
510 			conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
511 			params->private_key_passwd);
512 		if (ret != 0) {
513 			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
514 				   "PKCS#12 format: %s", gnutls_strerror(ret));
515 			return -1;
516 		} else
517 			pkcs12_ok = 1;
518 #endif /* PKCS12_FUNCS */
519 
520 		if (!pkcs12_ok) {
521 			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
522 				   "included");
523 			return -1;
524 		}
525 	} else if (params->client_cert_blob && params->private_key_blob) {
526 		gnutls_datum_t cert, key;
527 
528 		cert.data = (unsigned char *) params->client_cert_blob;
529 		cert.size = params->client_cert_blob_len;
530 		key.data = (unsigned char *) params->private_key_blob;
531 		key.size = params->private_key_blob_len;
532 
533 #if GNUTLS_VERSION_NUMBER >= 0x03010b
534 		ret = gnutls_certificate_set_x509_key_mem2(
535 			conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
536 			params->private_key_passwd, 0);
537 #else
538 		/* private_key_passwd not (easily) supported here */
539 		ret = gnutls_certificate_set_x509_key_mem(
540 			conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
541 #endif
542 		if (ret < 0) {
543 			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
544 				   "in DER format: %s", gnutls_strerror(ret));
545 #if GNUTLS_VERSION_NUMBER >= 0x03010b
546 			ret = gnutls_certificate_set_x509_key_mem2(
547 				conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
548 				params->private_key_passwd, 0);
549 #else
550 			/* private_key_passwd not (easily) supported here */
551 			ret = gnutls_certificate_set_x509_key_mem(
552 				conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
553 #endif
554 			if (ret < 0) {
555 				wpa_printf(MSG_DEBUG, "Failed to read client "
556 					   "cert/key in PEM format: %s",
557 					   gnutls_strerror(ret));
558 				return ret;
559 			}
560 		}
561 	} else if (params->private_key_blob) {
562 #ifdef PKCS12_FUNCS
563 		gnutls_datum_t key;
564 
565 		key.data = (unsigned char *) params->private_key_blob;
566 		key.size = params->private_key_blob_len;
567 
568 		/* Try to load in PKCS#12 format */
569 		ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
570 			conn->xcred, &key, GNUTLS_X509_FMT_DER,
571 			params->private_key_passwd);
572 		if (ret != 0) {
573 			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
574 				   "PKCS#12 format: %s", gnutls_strerror(ret));
575 			return -1;
576 		}
577 #else /* PKCS12_FUNCS */
578 		wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
579 		return -1;
580 #endif /* PKCS12_FUNCS */
581 	}
582 
583 #if GNUTLS_VERSION_NUMBER >= 0x030103
584 	if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
585 		ret = gnutls_ocsp_status_request_enable_client(conn->session,
586 							       NULL, 0, NULL);
587 		if (ret != GNUTLS_E_SUCCESS) {
588 			wpa_printf(MSG_INFO,
589 				   "GnuTLS: Failed to enable OCSP client");
590 			return -1;
591 		}
592 	}
593 #else /* 3.1.3 */
594 	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
595 		wpa_printf(MSG_INFO,
596 			   "GnuTLS: OCSP not supported by this version of GnuTLS");
597 		return -1;
598 	}
599 #endif /* 3.1.3 */
600 
601 	conn->params_set = 1;
602 
603 	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
604 				     conn->xcred);
605 	if (ret < 0) {
606 		wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
607 			   gnutls_strerror(ret));
608 	}
609 
610 	return ret;
611 }
612 
613 
614 #if GNUTLS_VERSION_NUMBER >= 0x030103
server_ocsp_status_req(gnutls_session_t session,void * ptr,gnutls_datum_t * resp)615 static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
616 				  gnutls_datum_t *resp)
617 {
618 	struct tls_global *global = ptr;
619 	char *cached;
620 	size_t len;
621 
622 	if (!global->ocsp_stapling_response) {
623 		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
624 		return GNUTLS_E_NO_CERTIFICATE_STATUS;
625 	}
626 
627 	cached = os_readfile(global->ocsp_stapling_response, &len);
628 	if (!cached) {
629 		wpa_printf(MSG_DEBUG,
630 			   "GnuTLS: OCSP status callback - could not read response file (%s)",
631 			   global->ocsp_stapling_response);
632 		return GNUTLS_E_NO_CERTIFICATE_STATUS;
633 	}
634 
635 	wpa_printf(MSG_DEBUG,
636 		   "GnuTLS: OCSP status callback - send cached response");
637 	resp->data = gnutls_malloc(len);
638 	if (!resp->data) {
639 		os_free(resp);
640 		return GNUTLS_E_MEMORY_ERROR;
641 	}
642 
643 	os_memcpy(resp->data, cached, len);
644 	resp->size = len;
645 	os_free(cached);
646 
647 	return GNUTLS_E_SUCCESS;
648 }
649 #endif /* 3.1.3 */
650 
651 
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)652 int tls_global_set_params(void *tls_ctx,
653 			  const struct tls_connection_params *params)
654 {
655 	struct tls_global *global = tls_ctx;
656 	int ret;
657 
658 	/* Currently, global parameters are only set when running in server
659 	 * mode. */
660 	global->server = 1;
661 
662 	if (global->params_set) {
663 		gnutls_certificate_free_credentials(global->xcred);
664 		global->params_set = 0;
665 	}
666 
667 	ret = gnutls_certificate_allocate_credentials(&global->xcred);
668 	if (ret) {
669 		wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
670 			   "%s", gnutls_strerror(ret));
671 		return -1;
672 	}
673 
674 	if (params->ca_cert) {
675 		ret = gnutls_certificate_set_x509_trust_file(
676 			global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
677 		if (ret < 0) {
678 			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
679 				   "in DER format: %s", params->ca_cert,
680 				   gnutls_strerror(ret));
681 			ret = gnutls_certificate_set_x509_trust_file(
682 				global->xcred, params->ca_cert,
683 				GNUTLS_X509_FMT_PEM);
684 			if (ret < 0) {
685 				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
686 					   "'%s' in PEM format: %s",
687 					   params->ca_cert,
688 					   gnutls_strerror(ret));
689 				goto fail;
690 			}
691 		}
692 
693 		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
694 			gnutls_certificate_set_verify_flags(
695 				global->xcred,
696 				GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
697 		}
698 
699 		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
700 			gnutls_certificate_set_verify_flags(
701 				global->xcred,
702 				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
703 		}
704 	}
705 
706 	if (params->client_cert && params->private_key) {
707 		/* TODO: private_key_passwd? */
708 		ret = gnutls_certificate_set_x509_key_file(
709 			global->xcred, params->client_cert,
710 			params->private_key, GNUTLS_X509_FMT_DER);
711 		if (ret < 0) {
712 			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
713 				   "in DER format: %s", gnutls_strerror(ret));
714 			ret = gnutls_certificate_set_x509_key_file(
715 				global->xcred, params->client_cert,
716 				params->private_key, GNUTLS_X509_FMT_PEM);
717 			if (ret < 0) {
718 				wpa_printf(MSG_DEBUG, "Failed to read client "
719 					   "cert/key in PEM format: %s",
720 					   gnutls_strerror(ret));
721 				goto fail;
722 			}
723 		}
724 	} else if (params->private_key) {
725 		int pkcs12_ok = 0;
726 #ifdef PKCS12_FUNCS
727 		/* Try to load in PKCS#12 format */
728 		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
729 			global->xcred, params->private_key,
730 			GNUTLS_X509_FMT_DER, params->private_key_passwd);
731 		if (ret != 0) {
732 			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
733 				   "PKCS#12 format: %s", gnutls_strerror(ret));
734 			goto fail;
735 		} else
736 			pkcs12_ok = 1;
737 #endif /* PKCS12_FUNCS */
738 
739 		if (!pkcs12_ok) {
740 			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
741 				   "included");
742 			goto fail;
743 		}
744 	}
745 
746 #if GNUTLS_VERSION_NUMBER >= 0x030103
747 	os_free(global->ocsp_stapling_response);
748 	if (params->ocsp_stapling_response)
749 		global->ocsp_stapling_response =
750 			os_strdup(params->ocsp_stapling_response);
751 	else
752 		global->ocsp_stapling_response = NULL;
753 	gnutls_certificate_set_ocsp_status_request_function(
754 		global->xcred, server_ocsp_status_req, global);
755 #endif /* 3.1.3 */
756 
757 	global->params_set = 1;
758 
759 	return 0;
760 
761 fail:
762 	gnutls_certificate_free_credentials(global->xcred);
763 	return -1;
764 }
765 
766 
tls_global_set_verify(void * ssl_ctx,int check_crl)767 int tls_global_set_verify(void *ssl_ctx, int check_crl)
768 {
769 	/* TODO */
770 	return 0;
771 }
772 
773 
tls_connection_set_verify(void * ssl_ctx,struct tls_connection * conn,int verify_peer,unsigned int flags,const u8 * session_ctx,size_t session_ctx_len)774 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
775 			      int verify_peer, unsigned int flags,
776 			      const u8 *session_ctx, size_t session_ctx_len)
777 {
778 	if (conn == NULL || conn->session == NULL)
779 		return -1;
780 
781 	conn->verify_peer = verify_peer;
782 	gnutls_certificate_server_set_request(conn->session,
783 					      verify_peer ? GNUTLS_CERT_REQUIRE
784 					      : GNUTLS_CERT_REQUEST);
785 
786 	return 0;
787 }
788 
789 
tls_connection_get_random(void * ssl_ctx,struct tls_connection * conn,struct tls_random * keys)790 int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
791 			    struct tls_random *keys)
792 {
793 #if GNUTLS_VERSION_NUMBER >= 0x030012
794 	gnutls_datum_t client, server;
795 
796 	if (conn == NULL || conn->session == NULL || keys == NULL)
797 		return -1;
798 
799 	os_memset(keys, 0, sizeof(*keys));
800 	gnutls_session_get_random(conn->session, &client, &server);
801 	keys->client_random = client.data;
802 	keys->server_random = server.data;
803 	keys->client_random_len = client.size;
804 	keys->server_random_len = client.size;
805 
806 	return 0;
807 #else /* 3.0.18 */
808 	return -1;
809 #endif /* 3.0.18 */
810 }
811 
812 
tls_connection_prf(void * tls_ctx,struct tls_connection * conn,const char * label,int server_random_first,int skip_keyblock,u8 * out,size_t out_len)813 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
814 		       const char *label, int server_random_first,
815 		       int skip_keyblock, u8 *out, size_t out_len)
816 {
817 	if (conn == NULL || conn->session == NULL || skip_keyblock)
818 		return -1;
819 
820 	return gnutls_prf(conn->session, os_strlen(label), label,
821 			  server_random_first, 0, NULL, out_len, (char *) out);
822 }
823 
824 
gnutls_tls_fail_event(struct tls_connection * conn,const gnutls_datum_t * cert,int depth,const char * subject,const char * err_str,enum tls_fail_reason reason)825 static void gnutls_tls_fail_event(struct tls_connection *conn,
826 				  const gnutls_datum_t *cert, int depth,
827 				  const char *subject, const char *err_str,
828 				  enum tls_fail_reason reason)
829 {
830 	union tls_event_data ev;
831 	struct tls_global *global = conn->global;
832 	struct wpabuf *cert_buf = NULL;
833 
834 	if (global->event_cb == NULL)
835 		return;
836 
837 	os_memset(&ev, 0, sizeof(ev));
838 	ev.cert_fail.depth = depth;
839 	ev.cert_fail.subject = subject ? subject : "";
840 	ev.cert_fail.reason = reason;
841 	ev.cert_fail.reason_txt = err_str;
842 	if (cert) {
843 		cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
844 		ev.cert_fail.cert = cert_buf;
845 	}
846 	global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
847 	wpabuf_free(cert_buf);
848 }
849 
850 
851 #if GNUTLS_VERSION_NUMBER < 0x030300
server_eku_purpose(gnutls_x509_crt_t cert)852 static int server_eku_purpose(gnutls_x509_crt_t cert)
853 {
854 	unsigned int i;
855 
856 	for (i = 0; ; i++) {
857 		char oid[128];
858 		size_t oid_size = sizeof(oid);
859 		int res;
860 
861 		res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
862 							  &oid_size, NULL);
863 		if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
864 			if (i == 0) {
865 				/* No EKU - assume any use allowed */
866 				return 1;
867 			}
868 			break;
869 		}
870 
871 		if (res < 0) {
872 			wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
873 			return 0;
874 		}
875 
876 		wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
877 		if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
878 		    os_strcmp(oid, GNUTLS_KP_ANY) == 0)
879 			return 1;
880 	}
881 
882 	return 0;
883 }
884 #endif /* < 3.3.0 */
885 
886 
check_ocsp(struct tls_connection * conn,gnutls_session_t session,gnutls_alert_description_t * err)887 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
888 		      gnutls_alert_description_t *err)
889 {
890 #if GNUTLS_VERSION_NUMBER >= 0x030103
891 	gnutls_datum_t response, buf;
892 	gnutls_ocsp_resp_t resp;
893 	unsigned int cert_status;
894 	int res;
895 
896 	if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
897 		return 0;
898 
899 	if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
900 		if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
901 			wpa_printf(MSG_INFO,
902 				   "GnuTLS: No valid OCSP response received");
903 			goto ocsp_error;
904 		}
905 
906 		wpa_printf(MSG_DEBUG,
907 			   "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
908 		return 0;
909 	}
910 
911 	/*
912 	 * GnuTLS has already verified the OCSP response in
913 	 * check_ocsp_response() and rejected handshake if the certificate was
914 	 * found to be revoked. However, if the response indicates that the
915 	 * status is unknown, handshake continues and reaches here. We need to
916 	 * re-import the OCSP response to check for unknown certificate status,
917 	 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
918 	 * gnutls_ocsp_resp_verify_direct() calls.
919 	 */
920 
921 	res = gnutls_ocsp_status_request_get(session, &response);
922 	if (res != GNUTLS_E_SUCCESS) {
923 		wpa_printf(MSG_INFO,
924 			   "GnuTLS: OCSP response was received, but it was not valid");
925 		goto ocsp_error;
926 	}
927 
928 	if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
929 		goto ocsp_error;
930 
931 	res = gnutls_ocsp_resp_import(resp, &response);
932 	if (res != GNUTLS_E_SUCCESS) {
933 		wpa_printf(MSG_INFO,
934 			   "GnuTLS: Could not parse received OCSP response: %s",
935 			   gnutls_strerror(res));
936 		gnutls_ocsp_resp_deinit(resp);
937 		goto ocsp_error;
938 	}
939 
940 	res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
941 	if (res == GNUTLS_E_SUCCESS) {
942 		wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
943 		gnutls_free(buf.data);
944 	}
945 
946 	res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
947 					  NULL, &cert_status, NULL,
948 					  NULL, NULL, NULL);
949 	gnutls_ocsp_resp_deinit(resp);
950 	if (res != GNUTLS_E_SUCCESS) {
951 		wpa_printf(MSG_INFO,
952 			   "GnuTLS: Failed to extract OCSP information: %s",
953 			   gnutls_strerror(res));
954 		goto ocsp_error;
955 	}
956 
957 	if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
958 		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
959 	} else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
960 		wpa_printf(MSG_DEBUG,
961 			   "GnuTLS: OCSP cert status: revoked");
962 		goto ocsp_error;
963 	} else {
964 		wpa_printf(MSG_DEBUG,
965 			   "GnuTLS: OCSP cert status: unknown");
966 		if (conn->flags & TLS_CONN_REQUIRE_OCSP)
967 			goto ocsp_error;
968 		wpa_printf(MSG_DEBUG,
969 			   "GnuTLS: OCSP was not required, so allow connection to continue");
970 	}
971 
972 	return 0;
973 
974 ocsp_error:
975 	gnutls_tls_fail_event(conn, NULL, 0, NULL,
976 			      "bad certificate status response",
977 			      TLS_FAIL_REVOKED);
978 	*err = GNUTLS_A_CERTIFICATE_REVOKED;
979 	return -1;
980 #else /* GnuTLS 3.1.3 or newer */
981 	return 0;
982 #endif /* GnuTLS 3.1.3 or newer */
983 }
984 
985 
tls_connection_verify_peer(gnutls_session_t session)986 static int tls_connection_verify_peer(gnutls_session_t session)
987 {
988 	struct tls_connection *conn;
989 	unsigned int status, num_certs, i;
990 	struct os_time now;
991 	const gnutls_datum_t *certs;
992 	gnutls_x509_crt_t cert;
993 	gnutls_alert_description_t err;
994 	int res;
995 
996 	conn = gnutls_session_get_ptr(session);
997 	if (!conn->verify_peer) {
998 		wpa_printf(MSG_DEBUG,
999 			   "GnuTLS: No peer certificate verification enabled");
1000 		return 0;
1001 	}
1002 
1003 	wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1004 
1005 #if GNUTLS_VERSION_NUMBER >= 0x030300
1006 	{
1007 		gnutls_typed_vdata_st data[1];
1008 		unsigned int elements = 0;
1009 
1010 		os_memset(data, 0, sizeof(data));
1011 		if (!conn->global->server) {
1012 			data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1013 			data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1014 			elements++;
1015 		}
1016 		res = gnutls_certificate_verify_peers(session, data, 1,
1017 						      &status);
1018 	}
1019 #else /* < 3.3.0 */
1020 	res = gnutls_certificate_verify_peers2(session, &status);
1021 #endif
1022 	if (res < 0) {
1023 		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1024 			   "certificate chain");
1025 		err = GNUTLS_A_INTERNAL_ERROR;
1026 		goto out;
1027 	}
1028 
1029 #if GNUTLS_VERSION_NUMBER >= 0x030104
1030 	{
1031 		gnutls_datum_t info;
1032 		int ret, type;
1033 
1034 		type = gnutls_certificate_type_get(session);
1035 		ret = gnutls_certificate_verification_status_print(status, type,
1036 								   &info, 0);
1037 		if (ret < 0) {
1038 			wpa_printf(MSG_DEBUG,
1039 				   "GnuTLS: Failed to print verification status");
1040 			err = GNUTLS_A_INTERNAL_ERROR;
1041 			goto out;
1042 		}
1043 		wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1044 		gnutls_free(info.data);
1045 	}
1046 #endif /* GnuTLS 3.1.4 or newer */
1047 
1048 	certs = gnutls_certificate_get_peers(session, &num_certs);
1049 	if (certs == NULL || num_certs == 0) {
1050 		wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1051 		err = GNUTLS_A_UNKNOWN_CA;
1052 		goto out;
1053 	}
1054 
1055 	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1056 		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1057 		if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1058 			wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1059 				   "algorithm");
1060 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1061 					      "certificate uses insecure algorithm",
1062 					      TLS_FAIL_BAD_CERTIFICATE);
1063 			err = GNUTLS_A_INSUFFICIENT_SECURITY;
1064 			goto out;
1065 		}
1066 		if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1067 			wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1068 				   "activated");
1069 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1070 					      "certificate not yet valid",
1071 					      TLS_FAIL_NOT_YET_VALID);
1072 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1073 			goto out;
1074 		}
1075 		if (status & GNUTLS_CERT_EXPIRED) {
1076 			wpa_printf(MSG_INFO, "TLS: Certificate expired");
1077 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1078 					      "certificate has expired",
1079 					      TLS_FAIL_EXPIRED);
1080 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1081 			goto out;
1082 		}
1083 		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1084 				      "untrusted certificate",
1085 				      TLS_FAIL_UNTRUSTED);
1086 		err = GNUTLS_A_INTERNAL_ERROR;
1087 		goto out;
1088 	}
1089 
1090 	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1091 		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1092 			   "known issuer");
1093 		gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1094 				      TLS_FAIL_UNTRUSTED);
1095 		err = GNUTLS_A_UNKNOWN_CA;
1096 		goto out;
1097 	}
1098 
1099 	if (status & GNUTLS_CERT_REVOKED) {
1100 		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1101 		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1102 				      "certificate revoked",
1103 				      TLS_FAIL_REVOKED);
1104 		err = GNUTLS_A_CERTIFICATE_REVOKED;
1105 		goto out;
1106 	}
1107 
1108 	if (status != 0) {
1109 		wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1110 			   status);
1111 		err = GNUTLS_A_INTERNAL_ERROR;
1112 		goto out;
1113 	}
1114 
1115 	if (check_ocsp(conn, session, &err))
1116 		goto out;
1117 
1118 	os_get_time(&now);
1119 
1120 	for (i = 0; i < num_certs; i++) {
1121 		char *buf;
1122 		size_t len;
1123 		if (gnutls_x509_crt_init(&cert) < 0) {
1124 			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1125 				   "failed");
1126 			err = GNUTLS_A_BAD_CERTIFICATE;
1127 			goto out;
1128 		}
1129 
1130 		if (gnutls_x509_crt_import(cert, &certs[i],
1131 					   GNUTLS_X509_FMT_DER) < 0) {
1132 			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1133 				   "certificate %d/%d", i + 1, num_certs);
1134 			gnutls_x509_crt_deinit(cert);
1135 			err = GNUTLS_A_BAD_CERTIFICATE;
1136 			goto out;
1137 		}
1138 
1139 		gnutls_x509_crt_get_dn(cert, NULL, &len);
1140 		len++;
1141 		buf = os_malloc(len + 1);
1142 		if (buf) {
1143 			buf[0] = buf[len] = '\0';
1144 			gnutls_x509_crt_get_dn(cert, buf, &len);
1145 		}
1146 		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1147 			   i + 1, num_certs, buf);
1148 
1149 		if (conn->global->event_cb) {
1150 			struct wpabuf *cert_buf = NULL;
1151 			union tls_event_data ev;
1152 #ifdef CONFIG_SHA256
1153 			u8 hash[32];
1154 			const u8 *_addr[1];
1155 			size_t _len[1];
1156 #endif /* CONFIG_SHA256 */
1157 
1158 			os_memset(&ev, 0, sizeof(ev));
1159 			if (conn->global->cert_in_cb) {
1160 				cert_buf = wpabuf_alloc_copy(certs[i].data,
1161 							     certs[i].size);
1162 				ev.peer_cert.cert = cert_buf;
1163 			}
1164 #ifdef CONFIG_SHA256
1165 			_addr[0] = certs[i].data;
1166 			_len[0] = certs[i].size;
1167 			if (sha256_vector(1, _addr, _len, hash) == 0) {
1168 				ev.peer_cert.hash = hash;
1169 				ev.peer_cert.hash_len = sizeof(hash);
1170 			}
1171 #endif /* CONFIG_SHA256 */
1172 			ev.peer_cert.depth = i;
1173 			ev.peer_cert.subject = buf;
1174 			conn->global->event_cb(conn->global->cb_ctx,
1175 					       TLS_PEER_CERTIFICATE, &ev);
1176 			wpabuf_free(cert_buf);
1177 		}
1178 
1179 		if (i == 0) {
1180 			if (conn->suffix_match &&
1181 			    !gnutls_x509_crt_check_hostname(
1182 				    cert, conn->suffix_match)) {
1183 				wpa_printf(MSG_WARNING,
1184 					   "TLS: Domain suffix match '%s' not found",
1185 					   conn->suffix_match);
1186 				gnutls_tls_fail_event(
1187 					conn, &certs[i], i, buf,
1188 					"Domain suffix mismatch",
1189 					TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1190 				err = GNUTLS_A_BAD_CERTIFICATE;
1191 				gnutls_x509_crt_deinit(cert);
1192 				os_free(buf);
1193 				goto out;
1194 			}
1195 
1196 #if GNUTLS_VERSION_NUMBER >= 0x030300
1197 			if (conn->domain_match &&
1198 			    !gnutls_x509_crt_check_hostname2(
1199 				    cert, conn->domain_match,
1200 				    GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
1201 				wpa_printf(MSG_WARNING,
1202 					   "TLS: Domain match '%s' not found",
1203 					   conn->domain_match);
1204 				gnutls_tls_fail_event(
1205 					conn, &certs[i], i, buf,
1206 					"Domain mismatch",
1207 					TLS_FAIL_DOMAIN_MISMATCH);
1208 				err = GNUTLS_A_BAD_CERTIFICATE;
1209 				gnutls_x509_crt_deinit(cert);
1210 				os_free(buf);
1211 				goto out;
1212 			}
1213 #endif /* >= 3.3.0 */
1214 
1215 			/* TODO: validate altsubject_match.
1216 			 * For now, any such configuration is rejected in
1217 			 * tls_connection_set_params() */
1218 
1219 #if GNUTLS_VERSION_NUMBER < 0x030300
1220 			/*
1221 			 * gnutls_certificate_verify_peers() not available, so
1222 			 * need to check EKU separately.
1223 			 */
1224 			if (!conn->global->server &&
1225 			    !server_eku_purpose(cert)) {
1226 				wpa_printf(MSG_WARNING,
1227 					   "GnuTLS: No server EKU");
1228 				gnutls_tls_fail_event(
1229 					conn, &certs[i], i, buf,
1230 					"No server EKU",
1231 					TLS_FAIL_BAD_CERTIFICATE);
1232 				err = GNUTLS_A_BAD_CERTIFICATE;
1233 				gnutls_x509_crt_deinit(cert);
1234 				os_free(buf);
1235 				goto out;
1236 			}
1237 #endif /* < 3.3.0 */
1238 		}
1239 
1240 		if (!conn->disable_time_checks &&
1241 		    (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1242 		     gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1243 			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1244 				   "not valid at this time",
1245 				   i + 1, num_certs);
1246 			gnutls_tls_fail_event(
1247 				conn, &certs[i], i, buf,
1248 				"Certificate is not valid at this time",
1249 				TLS_FAIL_EXPIRED);
1250 			gnutls_x509_crt_deinit(cert);
1251 			os_free(buf);
1252 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1253 			goto out;
1254 		}
1255 
1256 		os_free(buf);
1257 
1258 		gnutls_x509_crt_deinit(cert);
1259 	}
1260 
1261 	if (conn->global->event_cb != NULL)
1262 		conn->global->event_cb(conn->global->cb_ctx,
1263 				       TLS_CERT_CHAIN_SUCCESS, NULL);
1264 
1265 	return 0;
1266 
1267 out:
1268 	conn->failed++;
1269 	gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1270 	return GNUTLS_E_CERTIFICATE_ERROR;
1271 }
1272 
1273 
gnutls_get_appl_data(struct tls_connection * conn)1274 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1275 {
1276 	int res;
1277 	struct wpabuf *ad;
1278 	wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1279 	ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1280 	if (ad == NULL)
1281 		return NULL;
1282 
1283 	res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1284 				 wpabuf_size(ad));
1285 	wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1286 	if (res < 0) {
1287 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1288 			   "(%s)", __func__, (int) res,
1289 			   gnutls_strerror(res));
1290 		wpabuf_free(ad);
1291 		return NULL;
1292 	}
1293 
1294 	wpabuf_put(ad, res);
1295 	wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1296 		   res);
1297 	return ad;
1298 }
1299 
1300 
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)1301 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1302 					 struct tls_connection *conn,
1303 					 const struct wpabuf *in_data,
1304 					 struct wpabuf **appl_data)
1305 {
1306 	struct tls_global *global = tls_ctx;
1307 	struct wpabuf *out_data;
1308 	int ret;
1309 
1310 	if (appl_data)
1311 		*appl_data = NULL;
1312 
1313 	if (in_data && wpabuf_len(in_data) > 0) {
1314 		if (conn->pull_buf) {
1315 			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1316 				   "pull_buf", __func__,
1317 				   (unsigned long) wpabuf_len(conn->pull_buf));
1318 			wpabuf_free(conn->pull_buf);
1319 		}
1320 		conn->pull_buf = wpabuf_dup(in_data);
1321 		if (conn->pull_buf == NULL)
1322 			return NULL;
1323 		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1324 	}
1325 
1326 	ret = gnutls_handshake(conn->session);
1327 	if (ret < 0) {
1328 		gnutls_alert_description_t alert;
1329 
1330 		switch (ret) {
1331 		case GNUTLS_E_AGAIN:
1332 			if (global->server && conn->established &&
1333 			    conn->push_buf == NULL) {
1334 				/* Need to return something to trigger
1335 				 * completion of EAP-TLS. */
1336 				conn->push_buf = wpabuf_alloc(0);
1337 			}
1338 			break;
1339 		case GNUTLS_E_FATAL_ALERT_RECEIVED:
1340 			alert = gnutls_alert_get(conn->session);
1341 			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1342 				   __func__, gnutls_alert_get_name(alert));
1343 			conn->read_alerts++;
1344 			if (conn->global->event_cb != NULL) {
1345 				union tls_event_data ev;
1346 
1347 				os_memset(&ev, 0, sizeof(ev));
1348 				ev.alert.is_local = 0;
1349 				ev.alert.type = gnutls_alert_get_name(alert);
1350 				ev.alert.description = ev.alert.type;
1351 				conn->global->event_cb(conn->global->cb_ctx,
1352 						       TLS_ALERT, &ev);
1353 			}
1354 			/* continue */
1355 		default:
1356 			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1357 				   "-> %s", __func__, gnutls_strerror(ret));
1358 			conn->failed++;
1359 		}
1360 	} else {
1361 		size_t size;
1362 
1363 		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1364 
1365 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1366 		{
1367 			char *desc;
1368 
1369 			desc = gnutls_session_get_desc(conn->session);
1370 			if (desc) {
1371 				wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1372 				gnutls_free(desc);
1373 			}
1374 		}
1375 #endif /* GnuTLS 3.1.10 or newer */
1376 
1377 		conn->established = 1;
1378 		if (conn->push_buf == NULL) {
1379 			/* Need to return something to get final TLS ACK. */
1380 			conn->push_buf = wpabuf_alloc(0);
1381 		}
1382 
1383 		gnutls_session_get_data(conn->session, NULL, &size);
1384 		if (global->session_data == NULL ||
1385 		    global->session_data_size < size) {
1386 			os_free(global->session_data);
1387 			global->session_data = os_malloc(size);
1388 		}
1389 		if (global->session_data) {
1390 			global->session_data_size = size;
1391 			gnutls_session_get_data(conn->session,
1392 						global->session_data,
1393 						&global->session_data_size);
1394 		}
1395 
1396 		if (conn->pull_buf && appl_data)
1397 			*appl_data = gnutls_get_appl_data(conn);
1398 	}
1399 
1400 	out_data = conn->push_buf;
1401 	conn->push_buf = NULL;
1402 	return out_data;
1403 }
1404 
1405 
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)1406 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1407 						struct tls_connection *conn,
1408 						const struct wpabuf *in_data,
1409 						struct wpabuf **appl_data)
1410 {
1411 	return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1412 }
1413 
1414 
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)1415 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1416 				       struct tls_connection *conn,
1417 				       const struct wpabuf *in_data)
1418 {
1419 	ssize_t res;
1420 	struct wpabuf *buf;
1421 
1422 	res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1423 				 wpabuf_len(in_data));
1424 	if (res < 0) {
1425 		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1426 			   __func__, gnutls_strerror(res));
1427 		return NULL;
1428 	}
1429 
1430 	buf = conn->push_buf;
1431 	conn->push_buf = NULL;
1432 	return buf;
1433 }
1434 
1435 
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)1436 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1437 				       struct tls_connection *conn,
1438 				       const struct wpabuf *in_data)
1439 {
1440 	ssize_t res;
1441 	struct wpabuf *out;
1442 
1443 	if (conn->pull_buf) {
1444 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1445 			   "pull_buf", __func__,
1446 			   (unsigned long) wpabuf_len(conn->pull_buf));
1447 		wpabuf_free(conn->pull_buf);
1448 	}
1449 	conn->pull_buf = wpabuf_dup(in_data);
1450 	if (conn->pull_buf == NULL)
1451 		return NULL;
1452 	conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1453 
1454 	/*
1455 	 * Even though we try to disable TLS compression, it is possible that
1456 	 * this cannot be done with all TLS libraries. Add extra buffer space
1457 	 * to handle the possibility of the decrypted data being longer than
1458 	 * input data.
1459 	 */
1460 	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1461 	if (out == NULL)
1462 		return NULL;
1463 
1464 	res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1465 				 wpabuf_size(out));
1466 	if (res < 0) {
1467 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1468 			   "(%s)", __func__, (int) res, gnutls_strerror(res));
1469 		wpabuf_free(out);
1470 		return NULL;
1471 	}
1472 	wpabuf_put(out, res);
1473 
1474 	return out;
1475 }
1476 
1477 
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)1478 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1479 {
1480 	if (conn == NULL)
1481 		return 0;
1482 	return gnutls_session_is_resumed(conn->session);
1483 }
1484 
1485 
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)1486 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1487 				   u8 *ciphers)
1488 {
1489 	/* TODO */
1490 	return -1;
1491 }
1492 
1493 
tls_get_version(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)1494 int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1495 		    char *buf, size_t buflen)
1496 {
1497 	/* TODO */
1498 	return -1;
1499 }
1500 
1501 
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)1502 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1503 		   char *buf, size_t buflen)
1504 {
1505 	/* TODO */
1506 	buf[0] = '\0';
1507 	return 0;
1508 }
1509 
1510 
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)1511 int tls_connection_enable_workaround(void *ssl_ctx,
1512 				     struct tls_connection *conn)
1513 {
1514 	gnutls_record_disable_padding(conn->session);
1515 	return 0;
1516 }
1517 
1518 
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)1519 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1520 				    int ext_type, const u8 *data,
1521 				    size_t data_len)
1522 {
1523 	/* TODO */
1524 	return -1;
1525 }
1526 
1527 
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)1528 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1529 {
1530 	if (conn == NULL)
1531 		return -1;
1532 	return conn->failed;
1533 }
1534 
1535 
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)1536 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1537 {
1538 	if (conn == NULL)
1539 		return -1;
1540 	return conn->read_alerts;
1541 }
1542 
1543 
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)1544 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1545 {
1546 	if (conn == NULL)
1547 		return -1;
1548 	return conn->write_alerts;
1549 }
1550 
1551 
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)1552 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1553 					 struct tls_connection *conn,
1554 					 tls_session_ticket_cb cb, void *ctx)
1555 {
1556 	return -1;
1557 }
1558 
1559 
tls_get_library_version(char * buf,size_t buf_len)1560 int tls_get_library_version(char *buf, size_t buf_len)
1561 {
1562 	return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1563 			   GNUTLS_VERSION, gnutls_check_version(NULL));
1564 }
1565 
1566 
tls_connection_set_success_data(struct tls_connection * conn,struct wpabuf * data)1567 void tls_connection_set_success_data(struct tls_connection *conn,
1568 				     struct wpabuf *data)
1569 {
1570 }
1571 
1572 
tls_connection_set_success_data_resumed(struct tls_connection * conn)1573 void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1574 {
1575 }
1576 
1577 
1578 const struct wpabuf *
tls_connection_get_success_data(struct tls_connection * conn)1579 tls_connection_get_success_data(struct tls_connection *conn)
1580 {
1581 	return NULL;
1582 }
1583 
1584 
tls_connection_remove_session(struct tls_connection * conn)1585 void tls_connection_remove_session(struct tls_connection *conn)
1586 {
1587 }
1588