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