xref: /freebsd/contrib/wpa/src/crypto/tls_gnutls.c (revision 63cbe8d1d95f97e93929ec66f1138693d08dd9f6)
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 
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 
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 
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 
148 int tls_get_errors(void *ssl_ctx)
149 {
150 	return 0;
151 }
152 
153 
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 
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 
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 
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 
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 
292 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
293 {
294 	return conn ? conn->established : 0;
295 }
296 
297 
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 
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
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 
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 
767 int tls_global_set_verify(void *ssl_ctx, int check_crl)
768 {
769 	/* TODO */
770 	return 0;
771 }
772 
773 
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 
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 
813 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
814 			      const char *label, u8 *out, size_t out_len)
815 {
816 	if (conn == NULL || conn->session == NULL)
817 		return -1;
818 
819 	return gnutls_prf(conn->session, os_strlen(label), label,
820 			  0 /* client_random first */, 0, NULL, out_len,
821 			  (char *) out);
822 }
823 
824 
825 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
826 				    u8 *out, size_t out_len)
827 {
828 	return -1;
829 }
830 
831 
832 static void gnutls_tls_fail_event(struct tls_connection *conn,
833 				  const gnutls_datum_t *cert, int depth,
834 				  const char *subject, const char *err_str,
835 				  enum tls_fail_reason reason)
836 {
837 	union tls_event_data ev;
838 	struct tls_global *global = conn->global;
839 	struct wpabuf *cert_buf = NULL;
840 
841 	if (global->event_cb == NULL)
842 		return;
843 
844 	os_memset(&ev, 0, sizeof(ev));
845 	ev.cert_fail.depth = depth;
846 	ev.cert_fail.subject = subject ? subject : "";
847 	ev.cert_fail.reason = reason;
848 	ev.cert_fail.reason_txt = err_str;
849 	if (cert) {
850 		cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
851 		ev.cert_fail.cert = cert_buf;
852 	}
853 	global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
854 	wpabuf_free(cert_buf);
855 }
856 
857 
858 #if GNUTLS_VERSION_NUMBER < 0x030300
859 static int server_eku_purpose(gnutls_x509_crt_t cert)
860 {
861 	unsigned int i;
862 
863 	for (i = 0; ; i++) {
864 		char oid[128];
865 		size_t oid_size = sizeof(oid);
866 		int res;
867 
868 		res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
869 							  &oid_size, NULL);
870 		if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
871 			if (i == 0) {
872 				/* No EKU - assume any use allowed */
873 				return 1;
874 			}
875 			break;
876 		}
877 
878 		if (res < 0) {
879 			wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
880 			return 0;
881 		}
882 
883 		wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
884 		if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
885 		    os_strcmp(oid, GNUTLS_KP_ANY) == 0)
886 			return 1;
887 	}
888 
889 	return 0;
890 }
891 #endif /* < 3.3.0 */
892 
893 
894 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
895 		      gnutls_alert_description_t *err)
896 {
897 #if GNUTLS_VERSION_NUMBER >= 0x030103
898 	gnutls_datum_t response, buf;
899 	gnutls_ocsp_resp_t resp;
900 	unsigned int cert_status;
901 	int res;
902 
903 	if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
904 		return 0;
905 
906 	if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
907 		if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
908 			wpa_printf(MSG_INFO,
909 				   "GnuTLS: No valid OCSP response received");
910 			goto ocsp_error;
911 		}
912 
913 		wpa_printf(MSG_DEBUG,
914 			   "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
915 		return 0;
916 	}
917 
918 	/*
919 	 * GnuTLS has already verified the OCSP response in
920 	 * check_ocsp_response() and rejected handshake if the certificate was
921 	 * found to be revoked. However, if the response indicates that the
922 	 * status is unknown, handshake continues and reaches here. We need to
923 	 * re-import the OCSP response to check for unknown certificate status,
924 	 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
925 	 * gnutls_ocsp_resp_verify_direct() calls.
926 	 */
927 
928 	res = gnutls_ocsp_status_request_get(session, &response);
929 	if (res != GNUTLS_E_SUCCESS) {
930 		wpa_printf(MSG_INFO,
931 			   "GnuTLS: OCSP response was received, but it was not valid");
932 		goto ocsp_error;
933 	}
934 
935 	if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
936 		goto ocsp_error;
937 
938 	res = gnutls_ocsp_resp_import(resp, &response);
939 	if (res != GNUTLS_E_SUCCESS) {
940 		wpa_printf(MSG_INFO,
941 			   "GnuTLS: Could not parse received OCSP response: %s",
942 			   gnutls_strerror(res));
943 		gnutls_ocsp_resp_deinit(resp);
944 		goto ocsp_error;
945 	}
946 
947 	res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
948 	if (res == GNUTLS_E_SUCCESS) {
949 		wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
950 		gnutls_free(buf.data);
951 	}
952 
953 	res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
954 					  NULL, &cert_status, NULL,
955 					  NULL, NULL, NULL);
956 	gnutls_ocsp_resp_deinit(resp);
957 	if (res != GNUTLS_E_SUCCESS) {
958 		wpa_printf(MSG_INFO,
959 			   "GnuTLS: Failed to extract OCSP information: %s",
960 			   gnutls_strerror(res));
961 		goto ocsp_error;
962 	}
963 
964 	if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
965 		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
966 	} else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
967 		wpa_printf(MSG_DEBUG,
968 			   "GnuTLS: OCSP cert status: revoked");
969 		goto ocsp_error;
970 	} else {
971 		wpa_printf(MSG_DEBUG,
972 			   "GnuTLS: OCSP cert status: unknown");
973 		if (conn->flags & TLS_CONN_REQUIRE_OCSP)
974 			goto ocsp_error;
975 		wpa_printf(MSG_DEBUG,
976 			   "GnuTLS: OCSP was not required, so allow connection to continue");
977 	}
978 
979 	return 0;
980 
981 ocsp_error:
982 	gnutls_tls_fail_event(conn, NULL, 0, NULL,
983 			      "bad certificate status response",
984 			      TLS_FAIL_REVOKED);
985 	*err = GNUTLS_A_CERTIFICATE_REVOKED;
986 	return -1;
987 #else /* GnuTLS 3.1.3 or newer */
988 	return 0;
989 #endif /* GnuTLS 3.1.3 or newer */
990 }
991 
992 
993 static int tls_connection_verify_peer(gnutls_session_t session)
994 {
995 	struct tls_connection *conn;
996 	unsigned int status, num_certs, i;
997 	struct os_time now;
998 	const gnutls_datum_t *certs;
999 	gnutls_x509_crt_t cert;
1000 	gnutls_alert_description_t err;
1001 	int res;
1002 
1003 	conn = gnutls_session_get_ptr(session);
1004 	if (!conn->verify_peer) {
1005 		wpa_printf(MSG_DEBUG,
1006 			   "GnuTLS: No peer certificate verification enabled");
1007 		return 0;
1008 	}
1009 
1010 	wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1011 
1012 #if GNUTLS_VERSION_NUMBER >= 0x030300
1013 	{
1014 		gnutls_typed_vdata_st data[1];
1015 		unsigned int elements = 0;
1016 
1017 		os_memset(data, 0, sizeof(data));
1018 		if (!conn->global->server) {
1019 			data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1020 			data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1021 			elements++;
1022 		}
1023 		res = gnutls_certificate_verify_peers(session, data, 1,
1024 						      &status);
1025 	}
1026 #else /* < 3.3.0 */
1027 	res = gnutls_certificate_verify_peers2(session, &status);
1028 #endif
1029 	if (res < 0) {
1030 		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1031 			   "certificate chain");
1032 		err = GNUTLS_A_INTERNAL_ERROR;
1033 		goto out;
1034 	}
1035 
1036 #if GNUTLS_VERSION_NUMBER >= 0x030104
1037 	{
1038 		gnutls_datum_t info;
1039 		int ret, type;
1040 
1041 		type = gnutls_certificate_type_get(session);
1042 		ret = gnutls_certificate_verification_status_print(status, type,
1043 								   &info, 0);
1044 		if (ret < 0) {
1045 			wpa_printf(MSG_DEBUG,
1046 				   "GnuTLS: Failed to print verification status");
1047 			err = GNUTLS_A_INTERNAL_ERROR;
1048 			goto out;
1049 		}
1050 		wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1051 		gnutls_free(info.data);
1052 	}
1053 #endif /* GnuTLS 3.1.4 or newer */
1054 
1055 	certs = gnutls_certificate_get_peers(session, &num_certs);
1056 	if (certs == NULL || num_certs == 0) {
1057 		wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1058 		err = GNUTLS_A_UNKNOWN_CA;
1059 		goto out;
1060 	}
1061 
1062 	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1063 		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1064 		if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1065 			wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1066 				   "algorithm");
1067 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1068 					      "certificate uses insecure algorithm",
1069 					      TLS_FAIL_BAD_CERTIFICATE);
1070 			err = GNUTLS_A_INSUFFICIENT_SECURITY;
1071 			goto out;
1072 		}
1073 		if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1074 			wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1075 				   "activated");
1076 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1077 					      "certificate not yet valid",
1078 					      TLS_FAIL_NOT_YET_VALID);
1079 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1080 			goto out;
1081 		}
1082 		if (status & GNUTLS_CERT_EXPIRED) {
1083 			wpa_printf(MSG_INFO, "TLS: Certificate expired");
1084 			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1085 					      "certificate has expired",
1086 					      TLS_FAIL_EXPIRED);
1087 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1088 			goto out;
1089 		}
1090 		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1091 				      "untrusted certificate",
1092 				      TLS_FAIL_UNTRUSTED);
1093 		err = GNUTLS_A_INTERNAL_ERROR;
1094 		goto out;
1095 	}
1096 
1097 	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1098 		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1099 			   "known issuer");
1100 		gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1101 				      TLS_FAIL_UNTRUSTED);
1102 		err = GNUTLS_A_UNKNOWN_CA;
1103 		goto out;
1104 	}
1105 
1106 	if (status & GNUTLS_CERT_REVOKED) {
1107 		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1108 		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1109 				      "certificate revoked",
1110 				      TLS_FAIL_REVOKED);
1111 		err = GNUTLS_A_CERTIFICATE_REVOKED;
1112 		goto out;
1113 	}
1114 
1115 	if (status != 0) {
1116 		wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1117 			   status);
1118 		err = GNUTLS_A_INTERNAL_ERROR;
1119 		goto out;
1120 	}
1121 
1122 	if (check_ocsp(conn, session, &err))
1123 		goto out;
1124 
1125 	os_get_time(&now);
1126 
1127 	for (i = 0; i < num_certs; i++) {
1128 		char *buf;
1129 		size_t len;
1130 		if (gnutls_x509_crt_init(&cert) < 0) {
1131 			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1132 				   "failed");
1133 			err = GNUTLS_A_BAD_CERTIFICATE;
1134 			goto out;
1135 		}
1136 
1137 		if (gnutls_x509_crt_import(cert, &certs[i],
1138 					   GNUTLS_X509_FMT_DER) < 0) {
1139 			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1140 				   "certificate %d/%d", i + 1, num_certs);
1141 			gnutls_x509_crt_deinit(cert);
1142 			err = GNUTLS_A_BAD_CERTIFICATE;
1143 			goto out;
1144 		}
1145 
1146 		gnutls_x509_crt_get_dn(cert, NULL, &len);
1147 		len++;
1148 		buf = os_malloc(len + 1);
1149 		if (buf) {
1150 			buf[0] = buf[len] = '\0';
1151 			gnutls_x509_crt_get_dn(cert, buf, &len);
1152 		}
1153 		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1154 			   i + 1, num_certs, buf);
1155 
1156 		if (conn->global->event_cb) {
1157 			struct wpabuf *cert_buf = NULL;
1158 			union tls_event_data ev;
1159 #ifdef CONFIG_SHA256
1160 			u8 hash[32];
1161 			const u8 *_addr[1];
1162 			size_t _len[1];
1163 #endif /* CONFIG_SHA256 */
1164 
1165 			os_memset(&ev, 0, sizeof(ev));
1166 			if (conn->global->cert_in_cb) {
1167 				cert_buf = wpabuf_alloc_copy(certs[i].data,
1168 							     certs[i].size);
1169 				ev.peer_cert.cert = cert_buf;
1170 			}
1171 #ifdef CONFIG_SHA256
1172 			_addr[0] = certs[i].data;
1173 			_len[0] = certs[i].size;
1174 			if (sha256_vector(1, _addr, _len, hash) == 0) {
1175 				ev.peer_cert.hash = hash;
1176 				ev.peer_cert.hash_len = sizeof(hash);
1177 			}
1178 #endif /* CONFIG_SHA256 */
1179 			ev.peer_cert.depth = i;
1180 			ev.peer_cert.subject = buf;
1181 			conn->global->event_cb(conn->global->cb_ctx,
1182 					       TLS_PEER_CERTIFICATE, &ev);
1183 			wpabuf_free(cert_buf);
1184 		}
1185 
1186 		if (i == 0) {
1187 			if (conn->suffix_match &&
1188 			    !gnutls_x509_crt_check_hostname(
1189 				    cert, conn->suffix_match)) {
1190 				wpa_printf(MSG_WARNING,
1191 					   "TLS: Domain suffix match '%s' not found",
1192 					   conn->suffix_match);
1193 				gnutls_tls_fail_event(
1194 					conn, &certs[i], i, buf,
1195 					"Domain suffix mismatch",
1196 					TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1197 				err = GNUTLS_A_BAD_CERTIFICATE;
1198 				gnutls_x509_crt_deinit(cert);
1199 				os_free(buf);
1200 				goto out;
1201 			}
1202 
1203 #if GNUTLS_VERSION_NUMBER >= 0x030300
1204 			if (conn->domain_match &&
1205 			    !gnutls_x509_crt_check_hostname2(
1206 				    cert, conn->domain_match,
1207 				    GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
1208 				wpa_printf(MSG_WARNING,
1209 					   "TLS: Domain match '%s' not found",
1210 					   conn->domain_match);
1211 				gnutls_tls_fail_event(
1212 					conn, &certs[i], i, buf,
1213 					"Domain mismatch",
1214 					TLS_FAIL_DOMAIN_MISMATCH);
1215 				err = GNUTLS_A_BAD_CERTIFICATE;
1216 				gnutls_x509_crt_deinit(cert);
1217 				os_free(buf);
1218 				goto out;
1219 			}
1220 #endif /* >= 3.3.0 */
1221 
1222 			/* TODO: validate altsubject_match.
1223 			 * For now, any such configuration is rejected in
1224 			 * tls_connection_set_params() */
1225 
1226 #if GNUTLS_VERSION_NUMBER < 0x030300
1227 			/*
1228 			 * gnutls_certificate_verify_peers() not available, so
1229 			 * need to check EKU separately.
1230 			 */
1231 			if (!conn->global->server &&
1232 			    !server_eku_purpose(cert)) {
1233 				wpa_printf(MSG_WARNING,
1234 					   "GnuTLS: No server EKU");
1235 				gnutls_tls_fail_event(
1236 					conn, &certs[i], i, buf,
1237 					"No server EKU",
1238 					TLS_FAIL_BAD_CERTIFICATE);
1239 				err = GNUTLS_A_BAD_CERTIFICATE;
1240 				gnutls_x509_crt_deinit(cert);
1241 				os_free(buf);
1242 				goto out;
1243 			}
1244 #endif /* < 3.3.0 */
1245 		}
1246 
1247 		if (!conn->disable_time_checks &&
1248 		    (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1249 		     gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1250 			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1251 				   "not valid at this time",
1252 				   i + 1, num_certs);
1253 			gnutls_tls_fail_event(
1254 				conn, &certs[i], i, buf,
1255 				"Certificate is not valid at this time",
1256 				TLS_FAIL_EXPIRED);
1257 			gnutls_x509_crt_deinit(cert);
1258 			os_free(buf);
1259 			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1260 			goto out;
1261 		}
1262 
1263 		os_free(buf);
1264 
1265 		gnutls_x509_crt_deinit(cert);
1266 	}
1267 
1268 	if (conn->global->event_cb != NULL)
1269 		conn->global->event_cb(conn->global->cb_ctx,
1270 				       TLS_CERT_CHAIN_SUCCESS, NULL);
1271 
1272 	return 0;
1273 
1274 out:
1275 	conn->failed++;
1276 	gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1277 	return GNUTLS_E_CERTIFICATE_ERROR;
1278 }
1279 
1280 
1281 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1282 {
1283 	int res;
1284 	struct wpabuf *ad;
1285 	wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1286 	ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1287 	if (ad == NULL)
1288 		return NULL;
1289 
1290 	res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1291 				 wpabuf_size(ad));
1292 	wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1293 	if (res < 0) {
1294 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1295 			   "(%s)", __func__, (int) res,
1296 			   gnutls_strerror(res));
1297 		wpabuf_free(ad);
1298 		return NULL;
1299 	}
1300 
1301 	wpabuf_put(ad, res);
1302 	wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1303 		   res);
1304 	return ad;
1305 }
1306 
1307 
1308 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1309 					 struct tls_connection *conn,
1310 					 const struct wpabuf *in_data,
1311 					 struct wpabuf **appl_data)
1312 {
1313 	struct tls_global *global = tls_ctx;
1314 	struct wpabuf *out_data;
1315 	int ret;
1316 
1317 	if (appl_data)
1318 		*appl_data = NULL;
1319 
1320 	if (in_data && wpabuf_len(in_data) > 0) {
1321 		if (conn->pull_buf) {
1322 			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1323 				   "pull_buf", __func__,
1324 				   (unsigned long) wpabuf_len(conn->pull_buf));
1325 			wpabuf_free(conn->pull_buf);
1326 		}
1327 		conn->pull_buf = wpabuf_dup(in_data);
1328 		if (conn->pull_buf == NULL)
1329 			return NULL;
1330 		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1331 	}
1332 
1333 	ret = gnutls_handshake(conn->session);
1334 	if (ret < 0) {
1335 		gnutls_alert_description_t alert;
1336 
1337 		switch (ret) {
1338 		case GNUTLS_E_AGAIN:
1339 			if (global->server && conn->established &&
1340 			    conn->push_buf == NULL) {
1341 				/* Need to return something to trigger
1342 				 * completion of EAP-TLS. */
1343 				conn->push_buf = wpabuf_alloc(0);
1344 			}
1345 			break;
1346 		case GNUTLS_E_FATAL_ALERT_RECEIVED:
1347 			alert = gnutls_alert_get(conn->session);
1348 			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1349 				   __func__, gnutls_alert_get_name(alert));
1350 			conn->read_alerts++;
1351 			if (conn->global->event_cb != NULL) {
1352 				union tls_event_data ev;
1353 
1354 				os_memset(&ev, 0, sizeof(ev));
1355 				ev.alert.is_local = 0;
1356 				ev.alert.type = gnutls_alert_get_name(alert);
1357 				ev.alert.description = ev.alert.type;
1358 				conn->global->event_cb(conn->global->cb_ctx,
1359 						       TLS_ALERT, &ev);
1360 			}
1361 			/* continue */
1362 		default:
1363 			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1364 				   "-> %s", __func__, gnutls_strerror(ret));
1365 			conn->failed++;
1366 		}
1367 	} else {
1368 		size_t size;
1369 
1370 		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1371 
1372 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1373 		{
1374 			char *desc;
1375 
1376 			desc = gnutls_session_get_desc(conn->session);
1377 			if (desc) {
1378 				wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1379 				gnutls_free(desc);
1380 			}
1381 		}
1382 #endif /* GnuTLS 3.1.10 or newer */
1383 
1384 		conn->established = 1;
1385 		if (conn->push_buf == NULL) {
1386 			/* Need to return something to get final TLS ACK. */
1387 			conn->push_buf = wpabuf_alloc(0);
1388 		}
1389 
1390 		gnutls_session_get_data(conn->session, NULL, &size);
1391 		if (global->session_data == NULL ||
1392 		    global->session_data_size < size) {
1393 			os_free(global->session_data);
1394 			global->session_data = os_malloc(size);
1395 		}
1396 		if (global->session_data) {
1397 			global->session_data_size = size;
1398 			gnutls_session_get_data(conn->session,
1399 						global->session_data,
1400 						&global->session_data_size);
1401 		}
1402 
1403 		if (conn->pull_buf && appl_data)
1404 			*appl_data = gnutls_get_appl_data(conn);
1405 	}
1406 
1407 	out_data = conn->push_buf;
1408 	conn->push_buf = NULL;
1409 	return out_data;
1410 }
1411 
1412 
1413 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1414 						struct tls_connection *conn,
1415 						const struct wpabuf *in_data,
1416 						struct wpabuf **appl_data)
1417 {
1418 	return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1419 }
1420 
1421 
1422 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1423 				       struct tls_connection *conn,
1424 				       const struct wpabuf *in_data)
1425 {
1426 	ssize_t res;
1427 	struct wpabuf *buf;
1428 
1429 	res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1430 				 wpabuf_len(in_data));
1431 	if (res < 0) {
1432 		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1433 			   __func__, gnutls_strerror(res));
1434 		return NULL;
1435 	}
1436 
1437 	buf = conn->push_buf;
1438 	conn->push_buf = NULL;
1439 	return buf;
1440 }
1441 
1442 
1443 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1444 				       struct tls_connection *conn,
1445 				       const struct wpabuf *in_data)
1446 {
1447 	ssize_t res;
1448 	struct wpabuf *out;
1449 
1450 	if (conn->pull_buf) {
1451 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1452 			   "pull_buf", __func__,
1453 			   (unsigned long) wpabuf_len(conn->pull_buf));
1454 		wpabuf_free(conn->pull_buf);
1455 	}
1456 	conn->pull_buf = wpabuf_dup(in_data);
1457 	if (conn->pull_buf == NULL)
1458 		return NULL;
1459 	conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1460 
1461 	/*
1462 	 * Even though we try to disable TLS compression, it is possible that
1463 	 * this cannot be done with all TLS libraries. Add extra buffer space
1464 	 * to handle the possibility of the decrypted data being longer than
1465 	 * input data.
1466 	 */
1467 	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1468 	if (out == NULL)
1469 		return NULL;
1470 
1471 	res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1472 				 wpabuf_size(out));
1473 	if (res < 0) {
1474 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1475 			   "(%s)", __func__, (int) res, gnutls_strerror(res));
1476 		wpabuf_free(out);
1477 		return NULL;
1478 	}
1479 	wpabuf_put(out, res);
1480 
1481 	return out;
1482 }
1483 
1484 
1485 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1486 {
1487 	if (conn == NULL)
1488 		return 0;
1489 	return gnutls_session_is_resumed(conn->session);
1490 }
1491 
1492 
1493 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1494 				   u8 *ciphers)
1495 {
1496 	/* TODO */
1497 	return -1;
1498 }
1499 
1500 
1501 int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1502 		    char *buf, size_t buflen)
1503 {
1504 	/* TODO */
1505 	return -1;
1506 }
1507 
1508 
1509 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1510 		   char *buf, size_t buflen)
1511 {
1512 	/* TODO */
1513 	buf[0] = '\0';
1514 	return 0;
1515 }
1516 
1517 
1518 int tls_connection_enable_workaround(void *ssl_ctx,
1519 				     struct tls_connection *conn)
1520 {
1521 	gnutls_record_disable_padding(conn->session);
1522 	return 0;
1523 }
1524 
1525 
1526 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1527 				    int ext_type, const u8 *data,
1528 				    size_t data_len)
1529 {
1530 	/* TODO */
1531 	return -1;
1532 }
1533 
1534 
1535 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1536 {
1537 	if (conn == NULL)
1538 		return -1;
1539 	return conn->failed;
1540 }
1541 
1542 
1543 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1544 {
1545 	if (conn == NULL)
1546 		return -1;
1547 	return conn->read_alerts;
1548 }
1549 
1550 
1551 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1552 {
1553 	if (conn == NULL)
1554 		return -1;
1555 	return conn->write_alerts;
1556 }
1557 
1558 
1559 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1560 					 struct tls_connection *conn,
1561 					 tls_session_ticket_cb cb, void *ctx)
1562 {
1563 	return -1;
1564 }
1565 
1566 
1567 int tls_get_library_version(char *buf, size_t buf_len)
1568 {
1569 	return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1570 			   GNUTLS_VERSION, gnutls_check_version(NULL));
1571 }
1572 
1573 
1574 void tls_connection_set_success_data(struct tls_connection *conn,
1575 				     struct wpabuf *data)
1576 {
1577 }
1578 
1579 
1580 void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1581 {
1582 }
1583 
1584 
1585 const struct wpabuf *
1586 tls_connection_get_success_data(struct tls_connection *conn)
1587 {
1588 	return NULL;
1589 }
1590 
1591 
1592 void tls_connection_remove_session(struct tls_connection *conn)
1593 {
1594 }
1595