tls_gnutls.c revision 337817
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
24static int tls_gnutls_ref_count = 0;
25
26struct 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
44struct 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
68static int tls_connection_verify_peer(gnutls_session_t session);
69
70
71static 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
97void * 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
131void 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
148int tls_get_errors(void *ssl_ctx)
149{
150	return 0;
151}
152
153
154static 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
183static 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
198static 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
231fail:
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
239struct 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
276void 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
292int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
293{
294	return conn ? conn->established : 0;
295}
296
297
298int 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
345int 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
615static 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
652int 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
761fail:
762	gnutls_certificate_free_credentials(global->xcred);
763	return -1;
764}
765
766
767int tls_global_set_verify(void *ssl_ctx, int check_crl)
768{
769	/* TODO */
770	return 0;
771}
772
773
774int 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
790int 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
813int 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
825int 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
832static 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
859static 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
894static 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
981ocsp_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
993static 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
1274out:
1275	conn->failed++;
1276	gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1277	return GNUTLS_E_CERTIFICATE_ERROR;
1278}
1279
1280
1281static 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
1308struct 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
1413struct 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
1422struct 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
1443struct 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
1485int 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
1493int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1494				   u8 *ciphers)
1495{
1496	/* TODO */
1497	return -1;
1498}
1499
1500
1501int 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
1509int 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
1518int 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
1526int 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
1535int 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
1543int 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
1551int 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
1559int 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
1567int 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
1574void tls_connection_set_success_data(struct tls_connection *conn,
1575				     struct wpabuf *data)
1576{
1577}
1578
1579
1580void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1581{
1582}
1583
1584
1585const struct wpabuf *
1586tls_connection_get_success_data(struct tls_connection *conn)
1587{
1588	return NULL;
1589}
1590
1591
1592void tls_connection_remove_session(struct tls_connection *conn)
1593{
1594}
1595