1/*
2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2017, 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
298char * tls_connection_peer_serial_num(void *tls_ctx,
299				      struct tls_connection *conn)
300{
301	/* TODO */
302	return NULL;
303}
304
305
306int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
307{
308	struct tls_global *global = ssl_ctx;
309	int ret;
310
311	if (conn == NULL)
312		return -1;
313
314	/* Shutdown previous TLS connection without notifying the peer
315	 * because the connection was already terminated in practice
316	 * and "close notify" shutdown alert would confuse AS. */
317	gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
318	wpabuf_free(conn->push_buf);
319	conn->push_buf = NULL;
320	conn->established = 0;
321
322	gnutls_deinit(conn->session);
323	if (tls_gnutls_init_session(global, conn)) {
324		wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
325			   "for session resumption use");
326		return -1;
327	}
328
329	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
330				     conn->params_set ? conn->xcred :
331				     global->xcred);
332	if (ret < 0) {
333		wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
334			   "for session resumption: %s", gnutls_strerror(ret));
335		return -1;
336	}
337
338	if (global->session_data) {
339		ret = gnutls_session_set_data(conn->session,
340					      global->session_data,
341					      global->session_data_size);
342		if (ret < 0) {
343			wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
344				   "data: %s", gnutls_strerror(ret));
345			return -1;
346		}
347	}
348
349	return 0;
350}
351
352
353int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
354			      const struct tls_connection_params *params)
355{
356	int ret;
357	const char *err;
358	char prio_buf[100];
359	const char *prio = NULL;
360
361	if (conn == NULL || params == NULL)
362		return -1;
363
364	if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
365		wpa_printf(MSG_INFO,
366			   "GnuTLS: ocsp=3 not supported");
367		return -1;
368	}
369
370	if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
371		wpa_printf(MSG_INFO,
372			   "GnuTLS: tls_ext_cert_check=1 not supported");
373		return -1;
374	}
375
376	if (params->subject_match) {
377		wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
378		return -1;
379	}
380
381	if (params->altsubject_match) {
382		wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
383		return -1;
384	}
385
386	os_free(conn->suffix_match);
387	conn->suffix_match = NULL;
388	if (params->suffix_match) {
389		conn->suffix_match = os_strdup(params->suffix_match);
390		if (conn->suffix_match == NULL)
391			return -1;
392	}
393
394#if GNUTLS_VERSION_NUMBER >= 0x030300
395	os_free(conn->domain_match);
396	conn->domain_match = NULL;
397	if (params->domain_match) {
398		conn->domain_match = os_strdup(params->domain_match);
399		if (conn->domain_match == NULL)
400			return -1;
401	}
402#else /* < 3.3.0 */
403	if (params->domain_match) {
404		wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
405		return -1;
406	}
407#endif /* >= 3.3.0 */
408
409	conn->flags = params->flags;
410
411	if (params->flags & (TLS_CONN_DISABLE_TLSv1_0 |
412			     TLS_CONN_DISABLE_TLSv1_1 |
413			     TLS_CONN_DISABLE_TLSv1_2)) {
414		os_snprintf(prio_buf, sizeof(prio_buf),
415			    "NORMAL:-VERS-SSL3.0%s%s%s",
416			    params->flags & TLS_CONN_DISABLE_TLSv1_0 ?
417			    ":-VERS-TLS1.0" : "",
418			    params->flags & TLS_CONN_DISABLE_TLSv1_1 ?
419			    ":-VERS-TLS1.1" : "",
420			    params->flags & TLS_CONN_DISABLE_TLSv1_2 ?
421			    ":-VERS-TLS1.2" : "");
422		prio = prio_buf;
423	}
424
425	if (params->openssl_ciphers) {
426		if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
427			prio = "SUITEB128";
428		} else if (os_strcmp(params->openssl_ciphers,
429				     "SUITEB192") == 0) {
430			prio = "SUITEB192";
431		} else if ((params->flags & TLS_CONN_SUITEB) &&
432			   os_strcmp(params->openssl_ciphers,
433				     "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
434			prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
435		} else if (os_strcmp(params->openssl_ciphers,
436				     "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
437			prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
438		} else if (os_strcmp(params->openssl_ciphers,
439				     "DHE-RSA-AES256-GCM-SHA384") == 0) {
440			prio = "NONE:+VERS-TLS1.2:+AEAD:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
441		} else if (os_strcmp(params->openssl_ciphers,
442				     "ECDHE-ECDSA-AES256-GCM-SHA384") == 0) {
443			prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
444		} else {
445			wpa_printf(MSG_INFO,
446				   "GnuTLS: openssl_ciphers not supported");
447			return -1;
448		}
449	} else if (params->flags & TLS_CONN_SUITEB) {
450		prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
451	}
452
453	if (prio) {
454		wpa_printf(MSG_DEBUG, "GnuTLS: Set priority string: %s", prio);
455		ret = gnutls_priority_set_direct(conn->session, prio, &err);
456		if (ret < 0) {
457			wpa_printf(MSG_ERROR,
458				   "GnuTLS: Priority string failure at '%s'",
459				   err);
460			return -1;
461		}
462	}
463
464	if (params->openssl_ecdh_curves) {
465		wpa_printf(MSG_INFO,
466			   "GnuTLS: openssl_ecdh_curves not supported");
467		return -1;
468	}
469
470	/* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
471	 * to force peer validation(?) */
472
473	if (params->ca_cert) {
474		wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
475			   params->ca_cert);
476		ret = gnutls_certificate_set_x509_trust_file(
477			conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
478		if (ret < 0) {
479			wpa_printf(MSG_DEBUG,
480				   "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
481				   params->ca_cert,
482				   gnutls_strerror(ret));
483			ret = gnutls_certificate_set_x509_trust_file(
484				conn->xcred, params->ca_cert,
485				GNUTLS_X509_FMT_PEM);
486			if (ret < 0) {
487				wpa_printf(MSG_DEBUG,
488					   "Failed to read CA cert '%s' in PEM format: %s",
489					   params->ca_cert,
490					   gnutls_strerror(ret));
491				return -1;
492			}
493			wpa_printf(MSG_DEBUG,
494				   "GnuTLS: Successfully read CA cert '%s' in PEM format",
495				   params->ca_cert);
496		} else {
497			wpa_printf(MSG_DEBUG,
498				   "GnuTLS: Successfully read CA cert '%s' in DER format",
499				   params->ca_cert);
500		}
501	} else if (params->ca_cert_blob) {
502		gnutls_datum_t ca;
503
504		ca.data = (unsigned char *) params->ca_cert_blob;
505		ca.size = params->ca_cert_blob_len;
506
507		ret = gnutls_certificate_set_x509_trust_mem(
508			conn->xcred, &ca, GNUTLS_X509_FMT_DER);
509		if (ret < 0) {
510			wpa_printf(MSG_DEBUG,
511				   "Failed to parse CA cert in DER format: %s",
512				   gnutls_strerror(ret));
513			ret = gnutls_certificate_set_x509_trust_mem(
514				conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
515			if (ret < 0) {
516				wpa_printf(MSG_DEBUG,
517					   "Failed to parse CA cert in PEM format: %s",
518					   gnutls_strerror(ret));
519				return -1;
520			}
521		}
522	} else if (params->ca_path) {
523		wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
524		return -1;
525	}
526
527	conn->disable_time_checks = 0;
528	if (params->ca_cert || params->ca_cert_blob) {
529		conn->verify_peer = 1;
530		gnutls_certificate_set_verify_function(
531			conn->xcred, tls_connection_verify_peer);
532
533		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
534			gnutls_certificate_set_verify_flags(
535				conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
536		}
537
538		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
539			conn->disable_time_checks = 1;
540			gnutls_certificate_set_verify_flags(
541				conn->xcred,
542				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
543		}
544	}
545
546	if (params->client_cert && params->private_key) {
547		wpa_printf(MSG_DEBUG,
548			   "GnuTLS: Try to parse client cert '%s' and key '%s' in DER format",
549			   params->client_cert, params->private_key);
550#if GNUTLS_VERSION_NUMBER >= 0x03010b
551		ret = gnutls_certificate_set_x509_key_file2(
552			conn->xcred, params->client_cert, params->private_key,
553			GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
554#else
555		/* private_key_passwd not (easily) supported here */
556		ret = gnutls_certificate_set_x509_key_file(
557			conn->xcred, params->client_cert, params->private_key,
558			GNUTLS_X509_FMT_DER);
559#endif
560		if (ret < 0) {
561			wpa_printf(MSG_DEBUG,
562				   "GnuTLS: Failed to read client cert/key in DER format (%s) - try in PEM format",
563				   gnutls_strerror(ret));
564#if GNUTLS_VERSION_NUMBER >= 0x03010b
565			ret = gnutls_certificate_set_x509_key_file2(
566				conn->xcred, params->client_cert,
567				params->private_key, GNUTLS_X509_FMT_PEM,
568				params->private_key_passwd, 0);
569#else
570			ret = gnutls_certificate_set_x509_key_file(
571				conn->xcred, params->client_cert,
572				params->private_key, GNUTLS_X509_FMT_PEM);
573#endif
574			if (ret < 0) {
575				wpa_printf(MSG_DEBUG, "Failed to read client "
576					   "cert/key in PEM format: %s",
577					   gnutls_strerror(ret));
578				return ret;
579			}
580			wpa_printf(MSG_DEBUG,
581				   "GnuTLS: Successfully read client cert/key in PEM format");
582		} else {
583			wpa_printf(MSG_DEBUG,
584				   "GnuTLS: Successfully read client cert/key in DER format");
585		}
586	} else if (params->private_key) {
587		int pkcs12_ok = 0;
588#ifdef PKCS12_FUNCS
589		/* Try to load in PKCS#12 format */
590		wpa_printf(MSG_DEBUG,
591			   "GnuTLS: Try to parse client cert/key '%s'in PKCS#12 DER format",
592			   params->private_key);
593		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
594			conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
595			params->private_key_passwd);
596		if (ret != 0) {
597			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
598				   "PKCS#12 format: %s", gnutls_strerror(ret));
599			return -1;
600		} else
601			pkcs12_ok = 1;
602#endif /* PKCS12_FUNCS */
603
604		if (!pkcs12_ok) {
605			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
606				   "included");
607			return -1;
608		}
609	} else if (params->client_cert_blob && params->private_key_blob) {
610		gnutls_datum_t cert, key;
611
612		cert.data = (unsigned char *) params->client_cert_blob;
613		cert.size = params->client_cert_blob_len;
614		key.data = (unsigned char *) params->private_key_blob;
615		key.size = params->private_key_blob_len;
616
617#if GNUTLS_VERSION_NUMBER >= 0x03010b
618		ret = gnutls_certificate_set_x509_key_mem2(
619			conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
620			params->private_key_passwd, 0);
621#else
622		/* private_key_passwd not (easily) supported here */
623		ret = gnutls_certificate_set_x509_key_mem(
624			conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
625#endif
626		if (ret < 0) {
627			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
628				   "in DER format: %s", gnutls_strerror(ret));
629#if GNUTLS_VERSION_NUMBER >= 0x03010b
630			ret = gnutls_certificate_set_x509_key_mem2(
631				conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
632				params->private_key_passwd, 0);
633#else
634			/* private_key_passwd not (easily) supported here */
635			ret = gnutls_certificate_set_x509_key_mem(
636				conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
637#endif
638			if (ret < 0) {
639				wpa_printf(MSG_DEBUG, "Failed to read client "
640					   "cert/key in PEM format: %s",
641					   gnutls_strerror(ret));
642				return ret;
643			}
644		}
645	} else if (params->private_key_blob) {
646#ifdef PKCS12_FUNCS
647		gnutls_datum_t key;
648
649		key.data = (unsigned char *) params->private_key_blob;
650		key.size = params->private_key_blob_len;
651
652		/* Try to load in PKCS#12 format */
653		ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
654			conn->xcred, &key, GNUTLS_X509_FMT_DER,
655			params->private_key_passwd);
656		if (ret != 0) {
657			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
658				   "PKCS#12 format: %s", gnutls_strerror(ret));
659			return -1;
660		}
661#else /* PKCS12_FUNCS */
662		wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
663		return -1;
664#endif /* PKCS12_FUNCS */
665	}
666
667#if GNUTLS_VERSION_NUMBER >= 0x030103
668	if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
669		ret = gnutls_ocsp_status_request_enable_client(conn->session,
670							       NULL, 0, NULL);
671		if (ret != GNUTLS_E_SUCCESS) {
672			wpa_printf(MSG_INFO,
673				   "GnuTLS: Failed to enable OCSP client");
674			return -1;
675		}
676	}
677#else /* 3.1.3 */
678	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
679		wpa_printf(MSG_INFO,
680			   "GnuTLS: OCSP not supported by this version of GnuTLS");
681		return -1;
682	}
683#endif /* 3.1.3 */
684
685	conn->params_set = 1;
686
687	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
688				     conn->xcred);
689	if (ret < 0) {
690		wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
691			   gnutls_strerror(ret));
692	}
693
694	return ret;
695}
696
697
698#if GNUTLS_VERSION_NUMBER >= 0x030103
699static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
700				  gnutls_datum_t *resp)
701{
702	struct tls_global *global = ptr;
703	char *cached;
704	size_t len;
705
706	if (!global->ocsp_stapling_response) {
707		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
708		return GNUTLS_E_NO_CERTIFICATE_STATUS;
709	}
710
711	cached = os_readfile(global->ocsp_stapling_response, &len);
712	if (!cached) {
713		wpa_printf(MSG_DEBUG,
714			   "GnuTLS: OCSP status callback - could not read response file (%s)",
715			   global->ocsp_stapling_response);
716		return GNUTLS_E_NO_CERTIFICATE_STATUS;
717	}
718
719	wpa_printf(MSG_DEBUG,
720		   "GnuTLS: OCSP status callback - send cached response");
721	resp->data = gnutls_malloc(len);
722	if (!resp->data) {
723		os_free(resp);
724		return GNUTLS_E_MEMORY_ERROR;
725	}
726
727	os_memcpy(resp->data, cached, len);
728	resp->size = len;
729	os_free(cached);
730
731	return GNUTLS_E_SUCCESS;
732}
733#endif /* 3.1.3 */
734
735
736int tls_global_set_params(void *tls_ctx,
737			  const struct tls_connection_params *params)
738{
739	struct tls_global *global = tls_ctx;
740	int ret;
741
742	if (params->check_cert_subject)
743		return -1; /* not yet supported */
744
745	/* Currently, global parameters are only set when running in server
746	 * mode. */
747	global->server = 1;
748
749	if (global->params_set) {
750		gnutls_certificate_free_credentials(global->xcred);
751		global->params_set = 0;
752	}
753
754	ret = gnutls_certificate_allocate_credentials(&global->xcred);
755	if (ret) {
756		wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
757			   "%s", gnutls_strerror(ret));
758		return -1;
759	}
760
761	if (params->ca_cert) {
762		ret = gnutls_certificate_set_x509_trust_file(
763			global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
764		if (ret < 0) {
765			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
766				   "in DER format: %s", params->ca_cert,
767				   gnutls_strerror(ret));
768			ret = gnutls_certificate_set_x509_trust_file(
769				global->xcred, params->ca_cert,
770				GNUTLS_X509_FMT_PEM);
771			if (ret < 0) {
772				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
773					   "'%s' in PEM format: %s",
774					   params->ca_cert,
775					   gnutls_strerror(ret));
776				goto fail;
777			}
778		}
779
780		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
781			gnutls_certificate_set_verify_flags(
782				global->xcred,
783				GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
784		}
785
786		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
787			gnutls_certificate_set_verify_flags(
788				global->xcred,
789				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
790		}
791	}
792
793	if (params->client_cert && params->private_key) {
794		/* TODO: private_key_passwd? */
795		ret = gnutls_certificate_set_x509_key_file(
796			global->xcred, params->client_cert,
797			params->private_key, GNUTLS_X509_FMT_DER);
798		if (ret < 0) {
799			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
800				   "in DER format: %s", gnutls_strerror(ret));
801			ret = gnutls_certificate_set_x509_key_file(
802				global->xcred, params->client_cert,
803				params->private_key, GNUTLS_X509_FMT_PEM);
804			if (ret < 0) {
805				wpa_printf(MSG_DEBUG, "Failed to read client "
806					   "cert/key in PEM format: %s",
807					   gnutls_strerror(ret));
808				goto fail;
809			}
810		}
811	} else if (params->private_key) {
812		int pkcs12_ok = 0;
813#ifdef PKCS12_FUNCS
814		/* Try to load in PKCS#12 format */
815		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
816			global->xcred, params->private_key,
817			GNUTLS_X509_FMT_DER, params->private_key_passwd);
818		if (ret != 0) {
819			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
820				   "PKCS#12 format: %s", gnutls_strerror(ret));
821			goto fail;
822		} else
823			pkcs12_ok = 1;
824#endif /* PKCS12_FUNCS */
825
826		if (!pkcs12_ok) {
827			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
828				   "included");
829			goto fail;
830		}
831	}
832
833#if GNUTLS_VERSION_NUMBER >= 0x030103
834	os_free(global->ocsp_stapling_response);
835	if (params->ocsp_stapling_response)
836		global->ocsp_stapling_response =
837			os_strdup(params->ocsp_stapling_response);
838	else
839		global->ocsp_stapling_response = NULL;
840	gnutls_certificate_set_ocsp_status_request_function(
841		global->xcred, server_ocsp_status_req, global);
842#endif /* 3.1.3 */
843
844	global->params_set = 1;
845
846	return 0;
847
848fail:
849	gnutls_certificate_free_credentials(global->xcred);
850	return -1;
851}
852
853
854int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
855{
856	/* TODO */
857	return 0;
858}
859
860
861int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
862			      int verify_peer, unsigned int flags,
863			      const u8 *session_ctx, size_t session_ctx_len)
864{
865	if (conn == NULL || conn->session == NULL)
866		return -1;
867
868	conn->verify_peer = verify_peer;
869	gnutls_certificate_server_set_request(conn->session,
870					      verify_peer ? GNUTLS_CERT_REQUIRE
871					      : GNUTLS_CERT_REQUEST);
872
873	return 0;
874}
875
876
877int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
878			    struct tls_random *keys)
879{
880#if GNUTLS_VERSION_NUMBER >= 0x030012
881	gnutls_datum_t client, server;
882
883	if (conn == NULL || conn->session == NULL || keys == NULL)
884		return -1;
885
886	os_memset(keys, 0, sizeof(*keys));
887	gnutls_session_get_random(conn->session, &client, &server);
888	keys->client_random = client.data;
889	keys->server_random = server.data;
890	keys->client_random_len = client.size;
891	keys->server_random_len = client.size;
892
893	return 0;
894#else /* 3.0.18 */
895	return -1;
896#endif /* 3.0.18 */
897}
898
899
900int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
901			      const char *label, const u8 *context,
902			      size_t context_len, u8 *out, size_t out_len)
903{
904	if (conn == NULL || conn->session == NULL)
905		return -1;
906
907#if GNUTLS_VERSION_NUMBER >= 0x030404
908	return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
909				  context_len, (const char *) context,
910				  out_len, (char *) out);
911#else /* 3.4.4 */
912	if (context)
913		return -1;
914	return gnutls_prf(conn->session, os_strlen(label), label,
915			  0 /* client_random first */, 0, NULL, out_len,
916			  (char *) out);
917#endif /* 3.4.4 */
918}
919
920
921int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
922				    u8 *out, size_t out_len)
923{
924	return -1;
925}
926
927
928static void gnutls_tls_fail_event(struct tls_connection *conn,
929				  const gnutls_datum_t *cert, int depth,
930				  const char *subject, const char *err_str,
931				  enum tls_fail_reason reason)
932{
933	union tls_event_data ev;
934	struct tls_global *global = conn->global;
935	struct wpabuf *cert_buf = NULL;
936
937	if (global->event_cb == NULL)
938		return;
939
940	os_memset(&ev, 0, sizeof(ev));
941	ev.cert_fail.depth = depth;
942	ev.cert_fail.subject = subject ? subject : "";
943	ev.cert_fail.reason = reason;
944	ev.cert_fail.reason_txt = err_str;
945	if (cert) {
946		cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
947		ev.cert_fail.cert = cert_buf;
948	}
949	global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
950	wpabuf_free(cert_buf);
951}
952
953
954#if GNUTLS_VERSION_NUMBER < 0x030300
955static int server_eku_purpose(gnutls_x509_crt_t cert)
956{
957	unsigned int i;
958
959	for (i = 0; ; i++) {
960		char oid[128];
961		size_t oid_size = sizeof(oid);
962		int res;
963
964		res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
965							  &oid_size, NULL);
966		if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
967			if (i == 0) {
968				/* No EKU - assume any use allowed */
969				return 1;
970			}
971			break;
972		}
973
974		if (res < 0) {
975			wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
976			return 0;
977		}
978
979		wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
980		if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
981		    os_strcmp(oid, GNUTLS_KP_ANY) == 0)
982			return 1;
983	}
984
985	return 0;
986}
987#endif /* < 3.3.0 */
988
989
990static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
991		      gnutls_alert_description_t *err)
992{
993#if GNUTLS_VERSION_NUMBER >= 0x030103
994	gnutls_datum_t response, buf;
995	gnutls_ocsp_resp_t resp;
996	unsigned int cert_status;
997	int res;
998
999	if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
1000		return 0;
1001
1002	if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
1003		if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
1004			wpa_printf(MSG_INFO,
1005				   "GnuTLS: No valid OCSP response received");
1006			goto ocsp_error;
1007		}
1008
1009		wpa_printf(MSG_DEBUG,
1010			   "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
1011		return 0;
1012	}
1013
1014	/*
1015	 * GnuTLS has already verified the OCSP response in
1016	 * check_ocsp_response() and rejected handshake if the certificate was
1017	 * found to be revoked. However, if the response indicates that the
1018	 * status is unknown, handshake continues and reaches here. We need to
1019	 * re-import the OCSP response to check for unknown certificate status,
1020	 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
1021	 * gnutls_ocsp_resp_verify_direct() calls.
1022	 */
1023
1024	res = gnutls_ocsp_status_request_get(session, &response);
1025	if (res != GNUTLS_E_SUCCESS) {
1026		wpa_printf(MSG_INFO,
1027			   "GnuTLS: OCSP response was received, but it was not valid");
1028		goto ocsp_error;
1029	}
1030
1031	if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
1032		goto ocsp_error;
1033
1034	res = gnutls_ocsp_resp_import(resp, &response);
1035	if (res != GNUTLS_E_SUCCESS) {
1036		wpa_printf(MSG_INFO,
1037			   "GnuTLS: Could not parse received OCSP response: %s",
1038			   gnutls_strerror(res));
1039		gnutls_ocsp_resp_deinit(resp);
1040		goto ocsp_error;
1041	}
1042
1043	res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
1044	if (res == GNUTLS_E_SUCCESS) {
1045		wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
1046		gnutls_free(buf.data);
1047	}
1048
1049	res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
1050					  NULL, &cert_status, NULL,
1051					  NULL, NULL, NULL);
1052	gnutls_ocsp_resp_deinit(resp);
1053	if (res != GNUTLS_E_SUCCESS) {
1054		wpa_printf(MSG_INFO,
1055			   "GnuTLS: Failed to extract OCSP information: %s",
1056			   gnutls_strerror(res));
1057		goto ocsp_error;
1058	}
1059
1060	if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
1061		wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
1062	} else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
1063		wpa_printf(MSG_DEBUG,
1064			   "GnuTLS: OCSP cert status: revoked");
1065		goto ocsp_error;
1066	} else {
1067		wpa_printf(MSG_DEBUG,
1068			   "GnuTLS: OCSP cert status: unknown");
1069		if (conn->flags & TLS_CONN_REQUIRE_OCSP)
1070			goto ocsp_error;
1071		wpa_printf(MSG_DEBUG,
1072			   "GnuTLS: OCSP was not required, so allow connection to continue");
1073	}
1074
1075	return 0;
1076
1077ocsp_error:
1078	gnutls_tls_fail_event(conn, NULL, 0, NULL,
1079			      "bad certificate status response",
1080			      TLS_FAIL_REVOKED);
1081	*err = GNUTLS_A_CERTIFICATE_REVOKED;
1082	return -1;
1083#else /* GnuTLS 3.1.3 or newer */
1084	return 0;
1085#endif /* GnuTLS 3.1.3 or newer */
1086}
1087
1088
1089static int tls_match_suffix_helper(gnutls_x509_crt_t cert, const char *match,
1090				   int full)
1091{
1092	int res = -1;
1093
1094#if GNUTLS_VERSION_NUMBER >= 0x030300
1095	if (full)
1096		res = gnutls_x509_crt_check_hostname2(
1097			cert, match,
1098			GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS);
1099#endif /* >= 3.3.0 */
1100	if (res == -1)
1101		res = gnutls_x509_crt_check_hostname(cert, match);
1102
1103	wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s --> res=%d",
1104		   full ? "": "suffix ", match, res);
1105	return res;
1106}
1107
1108
1109static int tls_match_suffix(gnutls_x509_crt_t cert, const char *match,
1110			    int full)
1111{
1112	char *values, *token, *context = NULL;
1113	int ret = 0;
1114
1115	if (!os_strchr(match, ';'))
1116		return tls_match_suffix_helper(cert, match, full);
1117
1118	values = os_strdup(match);
1119	if (!values)
1120		return 0;
1121
1122	/* Process each match alternative separately until a match is found */
1123	while ((token = str_token(values, ";", &context))) {
1124		if (tls_match_suffix_helper(cert, token, full)) {
1125			ret = 1;
1126			break;
1127		}
1128	}
1129
1130	os_free(values);
1131	return ret;
1132}
1133
1134
1135static int tls_connection_verify_peer(gnutls_session_t session)
1136{
1137	struct tls_connection *conn;
1138	unsigned int status, num_certs, i;
1139	struct os_time now;
1140	const gnutls_datum_t *certs;
1141	gnutls_x509_crt_t cert;
1142	gnutls_alert_description_t err;
1143	int res;
1144
1145	conn = gnutls_session_get_ptr(session);
1146	if (!conn->verify_peer) {
1147		wpa_printf(MSG_DEBUG,
1148			   "GnuTLS: No peer certificate verification enabled");
1149		return 0;
1150	}
1151
1152	wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1153
1154#if GNUTLS_VERSION_NUMBER >= 0x030300
1155	{
1156		gnutls_typed_vdata_st data[1];
1157		unsigned int elements = 0;
1158
1159		os_memset(data, 0, sizeof(data));
1160		if (!conn->global->server) {
1161			data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1162			data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1163			elements++;
1164		}
1165		res = gnutls_certificate_verify_peers(session, data, 1,
1166						      &status);
1167	}
1168#else /* < 3.3.0 */
1169	res = gnutls_certificate_verify_peers2(session, &status);
1170#endif
1171	if (res < 0) {
1172		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1173			   "certificate chain");
1174		err = GNUTLS_A_INTERNAL_ERROR;
1175		goto out;
1176	}
1177
1178#if GNUTLS_VERSION_NUMBER >= 0x030104
1179	{
1180		gnutls_datum_t info;
1181		int ret, type;
1182
1183		type = gnutls_certificate_type_get(session);
1184		ret = gnutls_certificate_verification_status_print(status, type,
1185								   &info, 0);
1186		if (ret < 0) {
1187			wpa_printf(MSG_DEBUG,
1188				   "GnuTLS: Failed to print verification status");
1189			err = GNUTLS_A_INTERNAL_ERROR;
1190			goto out;
1191		}
1192		wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1193		gnutls_free(info.data);
1194	}
1195#endif /* GnuTLS 3.1.4 or newer */
1196
1197	certs = gnutls_certificate_get_peers(session, &num_certs);
1198	if (certs == NULL || num_certs == 0) {
1199		wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1200		err = GNUTLS_A_UNKNOWN_CA;
1201		goto out;
1202	}
1203
1204	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1205		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1206		if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1207			wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1208				   "algorithm");
1209			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1210					      "certificate uses insecure algorithm",
1211					      TLS_FAIL_BAD_CERTIFICATE);
1212			err = GNUTLS_A_INSUFFICIENT_SECURITY;
1213			goto out;
1214		}
1215		if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1216			wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1217				   "activated");
1218			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1219					      "certificate not yet valid",
1220					      TLS_FAIL_NOT_YET_VALID);
1221			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1222			goto out;
1223		}
1224		if (status & GNUTLS_CERT_EXPIRED) {
1225			wpa_printf(MSG_INFO, "TLS: Certificate expired");
1226			gnutls_tls_fail_event(conn, NULL, 0, NULL,
1227					      "certificate has expired",
1228					      TLS_FAIL_EXPIRED);
1229			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1230			goto out;
1231		}
1232		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1233				      "untrusted certificate",
1234				      TLS_FAIL_UNTRUSTED);
1235		err = GNUTLS_A_INTERNAL_ERROR;
1236		goto out;
1237	}
1238
1239	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1240		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1241			   "known issuer");
1242		gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1243				      TLS_FAIL_UNTRUSTED);
1244		err = GNUTLS_A_UNKNOWN_CA;
1245		goto out;
1246	}
1247
1248	if (status & GNUTLS_CERT_REVOKED) {
1249		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1250		gnutls_tls_fail_event(conn, NULL, 0, NULL,
1251				      "certificate revoked",
1252				      TLS_FAIL_REVOKED);
1253		err = GNUTLS_A_CERTIFICATE_REVOKED;
1254		goto out;
1255	}
1256
1257	if (status != 0) {
1258		wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1259			   status);
1260		err = GNUTLS_A_INTERNAL_ERROR;
1261		goto out;
1262	}
1263
1264	if (check_ocsp(conn, session, &err))
1265		goto out;
1266
1267	os_get_time(&now);
1268
1269	for (i = 0; i < num_certs; i++) {
1270		char *buf;
1271		size_t len;
1272		if (gnutls_x509_crt_init(&cert) < 0) {
1273			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1274				   "failed");
1275			err = GNUTLS_A_BAD_CERTIFICATE;
1276			goto out;
1277		}
1278
1279		if (gnutls_x509_crt_import(cert, &certs[i],
1280					   GNUTLS_X509_FMT_DER) < 0) {
1281			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1282				   "certificate %d/%d", i + 1, num_certs);
1283			gnutls_x509_crt_deinit(cert);
1284			err = GNUTLS_A_BAD_CERTIFICATE;
1285			goto out;
1286		}
1287
1288		gnutls_x509_crt_get_dn(cert, NULL, &len);
1289		len++;
1290		buf = os_malloc(len + 1);
1291		if (buf) {
1292			buf[0] = buf[len] = '\0';
1293			gnutls_x509_crt_get_dn(cert, buf, &len);
1294		}
1295		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1296			   i + 1, num_certs, buf);
1297
1298		if (conn->global->event_cb) {
1299			struct wpabuf *cert_buf = NULL;
1300			union tls_event_data ev;
1301#ifdef CONFIG_SHA256
1302			u8 hash[32];
1303			const u8 *_addr[1];
1304			size_t _len[1];
1305#endif /* CONFIG_SHA256 */
1306
1307			os_memset(&ev, 0, sizeof(ev));
1308			if (conn->global->cert_in_cb) {
1309				cert_buf = wpabuf_alloc_copy(certs[i].data,
1310							     certs[i].size);
1311				ev.peer_cert.cert = cert_buf;
1312			}
1313#ifdef CONFIG_SHA256
1314			_addr[0] = certs[i].data;
1315			_len[0] = certs[i].size;
1316			if (sha256_vector(1, _addr, _len, hash) == 0) {
1317				ev.peer_cert.hash = hash;
1318				ev.peer_cert.hash_len = sizeof(hash);
1319			}
1320#endif /* CONFIG_SHA256 */
1321			ev.peer_cert.depth = i;
1322			ev.peer_cert.subject = buf;
1323			conn->global->event_cb(conn->global->cb_ctx,
1324					       TLS_PEER_CERTIFICATE, &ev);
1325			wpabuf_free(cert_buf);
1326		}
1327
1328		if (i == 0) {
1329			if (conn->suffix_match &&
1330			    !tls_match_suffix(cert, conn->suffix_match, 0)) {
1331				wpa_printf(MSG_WARNING,
1332					   "TLS: Domain suffix match '%s' not found",
1333					   conn->suffix_match);
1334				gnutls_tls_fail_event(
1335					conn, &certs[i], i, buf,
1336					"Domain suffix mismatch",
1337					TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1338				err = GNUTLS_A_BAD_CERTIFICATE;
1339				gnutls_x509_crt_deinit(cert);
1340				os_free(buf);
1341				goto out;
1342			}
1343
1344#if GNUTLS_VERSION_NUMBER >= 0x030300
1345			if (conn->domain_match &&
1346			    !tls_match_suffix(cert, conn->domain_match, 1)) {
1347				wpa_printf(MSG_WARNING,
1348					   "TLS: Domain match '%s' not found",
1349					   conn->domain_match);
1350				gnutls_tls_fail_event(
1351					conn, &certs[i], i, buf,
1352					"Domain mismatch",
1353					TLS_FAIL_DOMAIN_MISMATCH);
1354				err = GNUTLS_A_BAD_CERTIFICATE;
1355				gnutls_x509_crt_deinit(cert);
1356				os_free(buf);
1357				goto out;
1358			}
1359#endif /* >= 3.3.0 */
1360
1361			/* TODO: validate altsubject_match.
1362			 * For now, any such configuration is rejected in
1363			 * tls_connection_set_params() */
1364
1365#if GNUTLS_VERSION_NUMBER < 0x030300
1366			/*
1367			 * gnutls_certificate_verify_peers() not available, so
1368			 * need to check EKU separately.
1369			 */
1370			if (!conn->global->server &&
1371			    !server_eku_purpose(cert)) {
1372				wpa_printf(MSG_WARNING,
1373					   "GnuTLS: No server EKU");
1374				gnutls_tls_fail_event(
1375					conn, &certs[i], i, buf,
1376					"No server EKU",
1377					TLS_FAIL_BAD_CERTIFICATE);
1378				err = GNUTLS_A_BAD_CERTIFICATE;
1379				gnutls_x509_crt_deinit(cert);
1380				os_free(buf);
1381				goto out;
1382			}
1383#endif /* < 3.3.0 */
1384		}
1385
1386		if (!conn->disable_time_checks &&
1387		    (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1388		     gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1389			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1390				   "not valid at this time",
1391				   i + 1, num_certs);
1392			gnutls_tls_fail_event(
1393				conn, &certs[i], i, buf,
1394				"Certificate is not valid at this time",
1395				TLS_FAIL_EXPIRED);
1396			gnutls_x509_crt_deinit(cert);
1397			os_free(buf);
1398			err = GNUTLS_A_CERTIFICATE_EXPIRED;
1399			goto out;
1400		}
1401
1402		os_free(buf);
1403
1404		gnutls_x509_crt_deinit(cert);
1405	}
1406
1407	if (conn->global->event_cb != NULL)
1408		conn->global->event_cb(conn->global->cb_ctx,
1409				       TLS_CERT_CHAIN_SUCCESS, NULL);
1410
1411	return 0;
1412
1413out:
1414	conn->failed++;
1415	gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1416	return GNUTLS_E_CERTIFICATE_ERROR;
1417}
1418
1419
1420static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1421{
1422	int res;
1423	struct wpabuf *ad;
1424	wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1425	ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1426	if (ad == NULL)
1427		return NULL;
1428
1429	res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1430				 wpabuf_size(ad));
1431	wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1432	if (res < 0) {
1433		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1434			   "(%s)", __func__, (int) res,
1435			   gnutls_strerror(res));
1436		wpabuf_free(ad);
1437		return NULL;
1438	}
1439
1440	wpabuf_put(ad, res);
1441	wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1442		   res);
1443	return ad;
1444}
1445
1446
1447struct wpabuf * tls_connection_handshake(void *tls_ctx,
1448					 struct tls_connection *conn,
1449					 const struct wpabuf *in_data,
1450					 struct wpabuf **appl_data)
1451{
1452	struct tls_global *global = tls_ctx;
1453	struct wpabuf *out_data;
1454	int ret;
1455
1456	if (appl_data)
1457		*appl_data = NULL;
1458
1459	if (in_data && wpabuf_len(in_data) > 0) {
1460		if (conn->pull_buf) {
1461			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1462				   "pull_buf", __func__,
1463				   (unsigned long) wpabuf_len(conn->pull_buf));
1464			wpabuf_free(conn->pull_buf);
1465		}
1466		conn->pull_buf = wpabuf_dup(in_data);
1467		if (conn->pull_buf == NULL)
1468			return NULL;
1469		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1470	}
1471
1472	ret = gnutls_handshake(conn->session);
1473	if (ret < 0) {
1474		gnutls_alert_description_t alert;
1475		union tls_event_data ev;
1476
1477		switch (ret) {
1478		case GNUTLS_E_AGAIN:
1479			if (global->server && conn->established &&
1480			    conn->push_buf == NULL) {
1481				/* Need to return something to trigger
1482				 * completion of EAP-TLS. */
1483				conn->push_buf = wpabuf_alloc(0);
1484			}
1485			break;
1486		case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
1487			wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
1488			if (conn->global->event_cb) {
1489				os_memset(&ev, 0, sizeof(ev));
1490				ev.alert.is_local = 1;
1491				ev.alert.type = "fatal";
1492				ev.alert.description = "insufficient security";
1493				conn->global->event_cb(conn->global->cb_ctx,
1494						       TLS_ALERT, &ev);
1495			}
1496			/*
1497			 * Could send a TLS Alert to the server, but for now,
1498			 * simply terminate handshake.
1499			 */
1500			conn->failed++;
1501			conn->write_alerts++;
1502			break;
1503		case GNUTLS_E_FATAL_ALERT_RECEIVED:
1504			alert = gnutls_alert_get(conn->session);
1505			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1506				   __func__, gnutls_alert_get_name(alert));
1507			conn->read_alerts++;
1508			if (conn->global->event_cb != NULL) {
1509				os_memset(&ev, 0, sizeof(ev));
1510				ev.alert.is_local = 0;
1511				ev.alert.type = gnutls_alert_get_name(alert);
1512				ev.alert.description = ev.alert.type;
1513				conn->global->event_cb(conn->global->cb_ctx,
1514						       TLS_ALERT, &ev);
1515			}
1516			/* continue */
1517		default:
1518			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1519				   "-> %s", __func__, gnutls_strerror(ret));
1520			conn->failed++;
1521		}
1522	} else {
1523		size_t size;
1524
1525		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1526
1527#if GNUTLS_VERSION_NUMBER >= 0x03010a
1528		{
1529			char *desc;
1530
1531			desc = gnutls_session_get_desc(conn->session);
1532			if (desc) {
1533				wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1534				gnutls_free(desc);
1535			}
1536		}
1537#endif /* GnuTLS 3.1.10 or newer */
1538
1539		conn->established = 1;
1540		if (conn->push_buf == NULL) {
1541			/* Need to return something to get final TLS ACK. */
1542			conn->push_buf = wpabuf_alloc(0);
1543		}
1544
1545		gnutls_session_get_data(conn->session, NULL, &size);
1546		if (global->session_data == NULL ||
1547		    global->session_data_size < size) {
1548			os_free(global->session_data);
1549			global->session_data = os_malloc(size);
1550		}
1551		if (global->session_data) {
1552			global->session_data_size = size;
1553			gnutls_session_get_data(conn->session,
1554						global->session_data,
1555						&global->session_data_size);
1556		}
1557
1558		if (conn->pull_buf && appl_data)
1559			*appl_data = gnutls_get_appl_data(conn);
1560	}
1561
1562	out_data = conn->push_buf;
1563	conn->push_buf = NULL;
1564	return out_data;
1565}
1566
1567
1568struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1569						struct tls_connection *conn,
1570						const struct wpabuf *in_data,
1571						struct wpabuf **appl_data)
1572{
1573	return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1574}
1575
1576
1577struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1578				       struct tls_connection *conn,
1579				       const struct wpabuf *in_data)
1580{
1581	ssize_t res;
1582	struct wpabuf *buf;
1583
1584	res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1585				 wpabuf_len(in_data));
1586	if (res < 0) {
1587		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1588			   __func__, gnutls_strerror(res));
1589		return NULL;
1590	}
1591
1592	buf = conn->push_buf;
1593	conn->push_buf = NULL;
1594	return buf;
1595}
1596
1597
1598struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1599				       struct tls_connection *conn,
1600				       const struct wpabuf *in_data)
1601{
1602	ssize_t res;
1603	struct wpabuf *out;
1604
1605	if (conn->pull_buf) {
1606		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1607			   "pull_buf", __func__,
1608			   (unsigned long) wpabuf_len(conn->pull_buf));
1609		wpabuf_free(conn->pull_buf);
1610	}
1611	conn->pull_buf = wpabuf_dup(in_data);
1612	if (conn->pull_buf == NULL)
1613		return NULL;
1614	conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1615
1616	/*
1617	 * Even though we try to disable TLS compression, it is possible that
1618	 * this cannot be done with all TLS libraries. Add extra buffer space
1619	 * to handle the possibility of the decrypted data being longer than
1620	 * input data.
1621	 */
1622	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1623	if (out == NULL)
1624		return NULL;
1625
1626	res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1627				 wpabuf_size(out));
1628	if (res < 0) {
1629		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1630			   "(%s)", __func__, (int) res, gnutls_strerror(res));
1631		wpabuf_free(out);
1632		return NULL;
1633	}
1634	wpabuf_put(out, res);
1635
1636	return out;
1637}
1638
1639
1640int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1641{
1642	if (conn == NULL)
1643		return 0;
1644	return gnutls_session_is_resumed(conn->session);
1645}
1646
1647
1648int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1649				   u8 *ciphers)
1650{
1651	/* TODO */
1652	return -1;
1653}
1654
1655
1656int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1657		    char *buf, size_t buflen)
1658{
1659	gnutls_protocol_t ver;
1660
1661	ver = gnutls_protocol_get_version(conn->session);
1662	if (ver == GNUTLS_TLS1_0)
1663		os_strlcpy(buf, "TLSv1", buflen);
1664	else if (ver == GNUTLS_TLS1_1)
1665		os_strlcpy(buf, "TLSv1.1", buflen);
1666	else if (ver == GNUTLS_TLS1_2)
1667		os_strlcpy(buf, "TLSv1.2", buflen);
1668	else
1669		return -1;
1670	return 0;
1671}
1672
1673
1674int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1675		   char *buf, size_t buflen)
1676{
1677	gnutls_cipher_algorithm_t cipher;
1678	gnutls_kx_algorithm_t kx;
1679	gnutls_mac_algorithm_t mac;
1680	const char *kx_str, *cipher_str, *mac_str;
1681	int res;
1682
1683	cipher = gnutls_cipher_get(conn->session);
1684	cipher_str = gnutls_cipher_get_name(cipher);
1685	if (!cipher_str)
1686		cipher_str = "";
1687
1688	kx = gnutls_kx_get(conn->session);
1689	kx_str = gnutls_kx_get_name(kx);
1690	if (!kx_str)
1691		kx_str = "";
1692
1693	mac = gnutls_mac_get(conn->session);
1694	mac_str = gnutls_mac_get_name(mac);
1695	if (!mac_str)
1696		mac_str = "";
1697
1698	if (kx == GNUTLS_KX_RSA)
1699		res = os_snprintf(buf, buflen, "%s-%s", cipher_str, mac_str);
1700	else
1701		res = os_snprintf(buf, buflen, "%s-%s-%s",
1702				  kx_str, cipher_str, mac_str);
1703	if (os_snprintf_error(buflen, res))
1704		return -1;
1705
1706	return 0;
1707}
1708
1709
1710int tls_connection_enable_workaround(void *ssl_ctx,
1711				     struct tls_connection *conn)
1712{
1713	gnutls_record_disable_padding(conn->session);
1714	return 0;
1715}
1716
1717
1718int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1719				    int ext_type, const u8 *data,
1720				    size_t data_len)
1721{
1722	/* TODO */
1723	return -1;
1724}
1725
1726
1727int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1728{
1729	if (conn == NULL)
1730		return -1;
1731	return conn->failed;
1732}
1733
1734
1735int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1736{
1737	if (conn == NULL)
1738		return -1;
1739	return conn->read_alerts;
1740}
1741
1742
1743int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1744{
1745	if (conn == NULL)
1746		return -1;
1747	return conn->write_alerts;
1748}
1749
1750
1751int tls_connection_set_session_ticket_cb(void *tls_ctx,
1752					 struct tls_connection *conn,
1753					 tls_session_ticket_cb cb, void *ctx)
1754{
1755	return -1;
1756}
1757
1758
1759int tls_get_library_version(char *buf, size_t buf_len)
1760{
1761	return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1762			   GNUTLS_VERSION, gnutls_check_version(NULL));
1763}
1764
1765
1766void tls_connection_set_success_data(struct tls_connection *conn,
1767				     struct wpabuf *data)
1768{
1769}
1770
1771
1772void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1773{
1774}
1775
1776
1777const struct wpabuf *
1778tls_connection_get_success_data(struct tls_connection *conn)
1779{
1780	return NULL;
1781}
1782
1783
1784void tls_connection_remove_session(struct tls_connection *conn)
1785{
1786}
1787