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