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