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 
     16 #include "common.h"
     17 #include "tls.h"
     18 
     19 
     20 #define WPA_TLS_RANDOM_SIZE 32
     21 #define WPA_TLS_MASTER_SIZE 48
     22 
     23 
     24 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
     25 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
     26  * use of internal structures to get the master_secret and
     27  * {server,client}_random.
     28  */
     29 #define GNUTLS_INTERNAL_STRUCTURE_HACK
     30 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
     31 
     32 
     33 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
     34 /*
     35  * It looks like gnutls does not provide access to client/server_random and
     36  * master_key. This is somewhat unfortunate since these are needed for key
     37  * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
     38  * hack that copies the gnutls_session_int definition from gnutls_int.h so that
     39  * we can get the needed information.
     40  */
     41 
     42 typedef u8 uint8;
     43 typedef unsigned char opaque;
     44 typedef struct {
     45     uint8 suite[2];
     46 } cipher_suite_st;
     47 
     48 typedef struct {
     49 	gnutls_connection_end_t entity;
     50 	gnutls_kx_algorithm_t kx_algorithm;
     51 	gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
     52 	gnutls_mac_algorithm_t read_mac_algorithm;
     53 	gnutls_compression_method_t read_compression_algorithm;
     54 	gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
     55 	gnutls_mac_algorithm_t write_mac_algorithm;
     56 	gnutls_compression_method_t write_compression_algorithm;
     57 	cipher_suite_st current_cipher_suite;
     58 	opaque master_secret[WPA_TLS_MASTER_SIZE];
     59 	opaque client_random[WPA_TLS_RANDOM_SIZE];
     60 	opaque server_random[WPA_TLS_RANDOM_SIZE];
     61 	/* followed by stuff we are not interested in */
     62 } security_parameters_st;
     63 
     64 struct gnutls_session_int {
     65 	security_parameters_st security_parameters;
     66 	/* followed by things we are not interested in */
     67 };
     68 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
     69 
     70 static int tls_gnutls_ref_count = 0;
     71 
     72 struct tls_global {
     73 	/* Data for session resumption */
     74 	void *session_data;
     75 	size_t session_data_size;
     76 
     77 	int server;
     78 
     79 	int params_set;
     80 	gnutls_certificate_credentials_t xcred;
     81 };
     82 
     83 struct tls_connection {
     84 	gnutls_session session;
     85 	char *subject_match, *altsubject_match;
     86 	int read_alerts, write_alerts, failed;
     87 
     88 	u8 *pre_shared_secret;
     89 	size_t pre_shared_secret_len;
     90 	int established;
     91 	int verify_peer;
     92 
     93 	struct wpabuf *push_buf;
     94 	struct wpabuf *pull_buf;
     95 	const u8 *pull_buf_offset;
     96 
     97 	int params_set;
     98 	gnutls_certificate_credentials_t xcred;
     99 };
    100 
    101 
    102 static void tls_log_func(int level, const char *msg)
    103 {
    104 	char *s, *pos;
    105 	if (level == 6 || level == 7) {
    106 		/* These levels seem to be mostly I/O debug and msg dumps */
    107 		return;
    108 	}
    109 
    110 	s = os_strdup(msg);
    111 	if (s == NULL)
    112 		return;
    113 
    114 	pos = s;
    115 	while (*pos != '\0') {
    116 		if (*pos == '\n') {
    117 			*pos = '\0';
    118 			break;
    119 		}
    120 		pos++;
    121 	}
    122 	wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
    123 		   "gnutls<%d> %s", level, s);
    124 	os_free(s);
    125 }
    126 
    127 
    128 extern int wpa_debug_show_keys;
    129 
    130 void * tls_init(const struct tls_config *conf)
    131 {
    132 	struct tls_global *global;
    133 
    134 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
    135 	/* Because of the horrible hack to get master_secret and client/server
    136 	 * random, we need to make sure that the gnutls version is something
    137 	 * that is expected to have same structure definition for the session
    138 	 * data.. */
    139 	const char *ver;
    140 	const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
    141 				 "1.3.2",
    142 				 NULL };
    143 	int i;
    144 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
    145 
    146 	global = os_zalloc(sizeof(*global));
    147 	if (global == NULL)
    148 		return NULL;
    149 
    150 	if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
    151 		os_free(global);
    152 		return NULL;
    153 	}
    154 	tls_gnutls_ref_count++;
    155 
    156 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
    157 	ver = gnutls_check_version(NULL);
    158 	if (ver == NULL) {
    159 		tls_deinit(global);
    160 		return NULL;
    161 	}
    162 	wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
    163 	for (i = 0; ok_ver[i]; i++) {
    164 		if (strcmp(ok_ver[i], ver) == 0)
    165 			break;
    166 	}
    167 	if (ok_ver[i] == NULL) {
    168 		wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
    169 			   "to be tested and enabled in tls_gnutls.c", ver);
    170 		tls_deinit(global);
    171 		return NULL;
    172 	}
    173 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
    174 
    175 	gnutls_global_set_log_function(tls_log_func);
    176 	if (wpa_debug_show_keys)
    177 		gnutls_global_set_log_level(11);
    178 	return global;
    179 }
    180 
    181 
    182 void tls_deinit(void *ssl_ctx)
    183 {
    184 	struct tls_global *global = ssl_ctx;
    185 	if (global) {
    186 		if (global->params_set)
    187 			gnutls_certificate_free_credentials(global->xcred);
    188 		os_free(global->session_data);
    189 		os_free(global);
    190 	}
    191 
    192 	tls_gnutls_ref_count--;
    193 	if (tls_gnutls_ref_count == 0)
    194 		gnutls_global_deinit();
    195 }
    196 
    197 
    198 int tls_get_errors(void *ssl_ctx)
    199 {
    200 	return 0;
    201 }
    202 
    203 
    204 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
    205 			     size_t len)
    206 {
    207 	struct tls_connection *conn = (struct tls_connection *) ptr;
    208 	const u8 *end;
    209 	if (conn->pull_buf == NULL) {
    210 		errno = EWOULDBLOCK;
    211 		return -1;
    212 	}
    213 
    214 	end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
    215 	if ((size_t) (end - conn->pull_buf_offset) < len)
    216 		len = end - conn->pull_buf_offset;
    217 	os_memcpy(buf, conn->pull_buf_offset, len);
    218 	conn->pull_buf_offset += len;
    219 	if (conn->pull_buf_offset == end) {
    220 		wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
    221 		wpabuf_free(conn->pull_buf);
    222 		conn->pull_buf = NULL;
    223 		conn->pull_buf_offset = NULL;
    224 	} else {
    225 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
    226 			   __func__,
    227 			   (unsigned long) (end - conn->pull_buf_offset));
    228 	}
    229 	return len;
    230 }
    231 
    232 
    233 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
    234 			     size_t len)
    235 {
    236 	struct tls_connection *conn = (struct tls_connection *) ptr;
    237 
    238 	if (wpabuf_resize(&conn->push_buf, len) < 0) {
    239 		errno = ENOMEM;
    240 		return -1;
    241 	}
    242 	wpabuf_put_data(conn->push_buf, buf, len);
    243 
    244 	return len;
    245 }
    246 
    247 
    248 static int tls_gnutls_init_session(struct tls_global *global,
    249 				   struct tls_connection *conn)
    250 {
    251 #if LIBGNUTLS_VERSION_NUMBER >= 0x020200
    252 	const char *err;
    253 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
    254 	const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
    255 	const int protos[2] = { GNUTLS_TLS1, 0 };
    256 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
    257 	int ret;
    258 
    259 	ret = gnutls_init(&conn->session,
    260 			  global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
    261 	if (ret < 0) {
    262 		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
    263 			   "connection: %s", gnutls_strerror(ret));
    264 		return -1;
    265 	}
    266 
    267 	ret = gnutls_set_default_priority(conn->session);
    268 	if (ret < 0)
    269 		goto fail;
    270 
    271 #if LIBGNUTLS_VERSION_NUMBER >= 0x020200
    272 	ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
    273 					 &err);
    274 	if (ret < 0) {
    275 		wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
    276 			   "'%s'", err);
    277 		goto fail;
    278 	}
    279 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
    280 	ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
    281 	if (ret < 0)
    282 		goto fail;
    283 
    284 	ret = gnutls_protocol_set_priority(conn->session, protos);
    285 	if (ret < 0)
    286 		goto fail;
    287 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
    288 
    289 	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
    290 	gnutls_transport_set_push_function(conn->session, tls_push_func);
    291 	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
    292 
    293 	return 0;
    294 
    295 fail:
    296 	wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
    297 		   gnutls_strerror(ret));
    298 	gnutls_deinit(conn->session);
    299 	return -1;
    300 }
    301 
    302 
    303 struct tls_connection * tls_connection_init(void *ssl_ctx)
    304 {
    305 	struct tls_global *global = ssl_ctx;
    306 	struct tls_connection *conn;
    307 	int ret;
    308 
    309 	conn = os_zalloc(sizeof(*conn));
    310 	if (conn == NULL)
    311 		return NULL;
    312 
    313 	if (tls_gnutls_init_session(global, conn)) {
    314 		os_free(conn);
    315 		return NULL;
    316 	}
    317 
    318 	if (global->params_set) {
    319 		ret = gnutls_credentials_set(conn->session,
    320 					     GNUTLS_CRD_CERTIFICATE,
    321 					     global->xcred);
    322 		if (ret < 0) {
    323 			wpa_printf(MSG_INFO, "Failed to configure "
    324 				   "credentials: %s", gnutls_strerror(ret));
    325 			os_free(conn);
    326 			return NULL;
    327 		}
    328 	}
    329 
    330 	if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
    331 		os_free(conn);
    332 		return NULL;
    333 	}
    334 
    335 	return conn;
    336 }
    337 
    338 
    339 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
    340 {
    341 	if (conn == NULL)
    342 		return;
    343 
    344 	gnutls_certificate_free_credentials(conn->xcred);
    345 	gnutls_deinit(conn->session);
    346 	os_free(conn->pre_shared_secret);
    347 	os_free(conn->subject_match);
    348 	os_free(conn->altsubject_match);
    349 	wpabuf_free(conn->push_buf);
    350 	wpabuf_free(conn->pull_buf);
    351 	os_free(conn);
    352 }
    353 
    354 
    355 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
    356 {
    357 	return conn ? conn->established : 0;
    358 }
    359 
    360 
    361 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
    362 {
    363 	struct tls_global *global = ssl_ctx;
    364 	int ret;
    365 
    366 	if (conn == NULL)
    367 		return -1;
    368 
    369 	/* Shutdown previous TLS connection without notifying the peer
    370 	 * because the connection was already terminated in practice
    371 	 * and "close notify" shutdown alert would confuse AS. */
    372 	gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
    373 	wpabuf_free(conn->push_buf);
    374 	conn->push_buf = NULL;
    375 	conn->established = 0;
    376 
    377 	gnutls_deinit(conn->session);
    378 	if (tls_gnutls_init_session(global, conn)) {
    379 		wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
    380 			   "for session resumption use");
    381 		return -1;
    382 	}
    383 
    384 	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
    385 				     conn->params_set ? conn->xcred :
    386 				     global->xcred);
    387 	if (ret < 0) {
    388 		wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
    389 			   "for session resumption: %s", gnutls_strerror(ret));
    390 		return -1;
    391 	}
    392 
    393 	if (global->session_data) {
    394 		ret = gnutls_session_set_data(conn->session,
    395 					      global->session_data,
    396 					      global->session_data_size);
    397 		if (ret < 0) {
    398 			wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
    399 				   "data: %s", gnutls_strerror(ret));
    400 			return -1;
    401 		}
    402 	}
    403 
    404 	return 0;
    405 }
    406 
    407 
    408 #if 0
    409 static int tls_match_altsubject(X509 *cert, const char *match)
    410 {
    411 	GENERAL_NAME *gen;
    412 	char *field, *tmp;
    413 	void *ext;
    414 	int i, found = 0;
    415 	size_t len;
    416 
    417 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
    418 
    419 	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
    420 		gen = sk_GENERAL_NAME_value(ext, i);
    421 		switch (gen->type) {
    422 		case GEN_EMAIL:
    423 			field = "EMAIL";
    424 			break;
    425 		case GEN_DNS:
    426 			field = "DNS";
    427 			break;
    428 		case GEN_URI:
    429 			field = "URI";
    430 			break;
    431 		default:
    432 			field = NULL;
    433 			wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
    434 				   "unsupported type=%d", gen->type);
    435 			break;
    436 		}
    437 
    438 		if (!field)
    439 			continue;
    440 
    441 		wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
    442 			   field, gen->d.ia5->data);
    443 		len = os_strlen(field) + 1 +
    444 			strlen((char *) gen->d.ia5->data) + 1;
    445 		tmp = os_malloc(len);
    446 		if (tmp == NULL)
    447 			continue;
    448 		snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
    449 		if (strstr(tmp, match))
    450 			found++;
    451 		os_free(tmp);
    452 	}
    453 
    454 	return found;
    455 }
    456 #endif
    457 
    458 
    459 #if 0
    460 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
    461 {
    462 	char buf[256];
    463 	X509 *err_cert;
    464 	int err, depth;
    465 	SSL *ssl;
    466 	struct tls_connection *conn;
    467 	char *match, *altmatch;
    468 
    469 	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
    470 	err = X509_STORE_CTX_get_error(x509_ctx);
    471 	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
    472 	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
    473 					 SSL_get_ex_data_X509_STORE_CTX_idx());
    474 	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
    475 
    476 	conn = SSL_get_app_data(ssl);
    477 	match = conn ? conn->subject_match : NULL;
    478 	altmatch = conn ? conn->altsubject_match : NULL;
    479 
    480 	if (!preverify_ok) {
    481 		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
    482 			   " error %d (%s) depth %d for '%s'", err,
    483 			   X509_verify_cert_error_string(err), depth, buf);
    484 	} else {
    485 		wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
    486 			   "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
    487 			   preverify_ok, err,
    488 			   X509_verify_cert_error_string(err), depth, buf);
    489 		if (depth == 0 && match && strstr(buf, match) == NULL) {
    490 			wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
    491 				   "match with '%s'", buf, match);
    492 			preverify_ok = 0;
    493 		} else if (depth == 0 && altmatch &&
    494 			   !tls_match_altsubject(err_cert, altmatch)) {
    495 			wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
    496 				   "'%s' not found", altmatch);
    497 			preverify_ok = 0;
    498 		}
    499 	}
    500 
    501 	return preverify_ok;
    502 }
    503 #endif
    504 
    505 
    506 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
    507 			      const struct tls_connection_params *params)
    508 {
    509 	int ret;
    510 
    511 	if (conn == NULL || params == NULL)
    512 		return -1;
    513 
    514 	os_free(conn->subject_match);
    515 	conn->subject_match = NULL;
    516 	if (params->subject_match) {
    517 		conn->subject_match = os_strdup(params->subject_match);
    518 		if (conn->subject_match == NULL)
    519 			return -1;
    520 	}
    521 
    522 	os_free(conn->altsubject_match);
    523 	conn->altsubject_match = NULL;
    524 	if (params->altsubject_match) {
    525 		conn->altsubject_match = os_strdup(params->altsubject_match);
    526 		if (conn->altsubject_match == NULL)
    527 			return -1;
    528 	}
    529 
    530 	/* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
    531 	 * to force peer validation(?) */
    532 
    533 	if (params->ca_cert) {
    534 		conn->verify_peer = 1;
    535 		ret = gnutls_certificate_set_x509_trust_file(
    536 			conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
    537 		if (ret < 0) {
    538 			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
    539 				   "in PEM format: %s", params->ca_cert,
    540 				   gnutls_strerror(ret));
    541 			ret = gnutls_certificate_set_x509_trust_file(
    542 				conn->xcred, params->ca_cert,
    543 				GNUTLS_X509_FMT_DER);
    544 			if (ret < 0) {
    545 				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
    546 					   "'%s' in DER format: %s",
    547 					   params->ca_cert,
    548 					   gnutls_strerror(ret));
    549 				return -1;
    550 			}
    551 		}
    552 
    553 		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
    554 			gnutls_certificate_set_verify_flags(
    555 				conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
    556 		}
    557 
    558 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
    559 		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
    560 			gnutls_certificate_set_verify_flags(
    561 				conn->xcred,
    562 				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
    563 		}
    564 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
    565 	}
    566 
    567 	if (params->client_cert && params->private_key) {
    568 		/* TODO: private_key_passwd? */
    569 		ret = gnutls_certificate_set_x509_key_file(
    570 			conn->xcred, params->client_cert, params->private_key,
    571 			GNUTLS_X509_FMT_PEM);
    572 		if (ret < 0) {
    573 			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
    574 				   "in PEM format: %s", gnutls_strerror(ret));
    575 			ret = gnutls_certificate_set_x509_key_file(
    576 				conn->xcred, params->client_cert,
    577 				params->private_key, GNUTLS_X509_FMT_DER);
    578 			if (ret < 0) {
    579 				wpa_printf(MSG_DEBUG, "Failed to read client "
    580 					   "cert/key in DER format: %s",
    581 					   gnutls_strerror(ret));
    582 				return ret;
    583 			}
    584 		}
    585 	} else if (params->private_key) {
    586 		int pkcs12_ok = 0;
    587 #ifdef PKCS12_FUNCS
    588 		/* Try to load in PKCS#12 format */
    589 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
    590 		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
    591 			conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
    592 			params->private_key_passwd);
    593 		if (ret != 0) {
    594 			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
    595 				   "PKCS#12 format: %s", gnutls_strerror(ret));
    596 			return -1;
    597 		} else
    598 			pkcs12_ok = 1;
    599 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
    600 #endif /* PKCS12_FUNCS */
    601 
    602 		if (!pkcs12_ok) {
    603 			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
    604 				   "included");
    605 			return -1;
    606 		}
    607 	}
    608 
    609 	conn->params_set = 1;
    610 
    611 	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
    612 				     conn->xcred);
    613 	if (ret < 0) {
    614 		wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
    615 			   gnutls_strerror(ret));
    616 	}
    617 
    618 	return ret;
    619 }
    620 
    621 
    622 int tls_global_set_params(void *tls_ctx,
    623 			  const struct tls_connection_params *params)
    624 {
    625 	struct tls_global *global = tls_ctx;
    626 	int ret;
    627 
    628 	/* Currently, global parameters are only set when running in server
    629 	 * mode. */
    630 	global->server = 1;
    631 
    632 	if (global->params_set) {
    633 		gnutls_certificate_free_credentials(global->xcred);
    634 		global->params_set = 0;
    635 	}
    636 
    637 	ret = gnutls_certificate_allocate_credentials(&global->xcred);
    638 	if (ret) {
    639 		wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
    640 			   "%s", gnutls_strerror(ret));
    641 		return -1;
    642 	}
    643 
    644 	if (params->ca_cert) {
    645 		ret = gnutls_certificate_set_x509_trust_file(
    646 			global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
    647 		if (ret < 0) {
    648 			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
    649 				   "in PEM format: %s", params->ca_cert,
    650 				   gnutls_strerror(ret));
    651 			ret = gnutls_certificate_set_x509_trust_file(
    652 				global->xcred, params->ca_cert,
    653 				GNUTLS_X509_FMT_DER);
    654 			if (ret < 0) {
    655 				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
    656 					   "'%s' in DER format: %s",
    657 					   params->ca_cert,
    658 					   gnutls_strerror(ret));
    659 				goto fail;
    660 			}
    661 		}
    662 
    663 		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
    664 			gnutls_certificate_set_verify_flags(
    665 				global->xcred,
    666 				GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
    667 		}
    668 
    669 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
    670 		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
    671 			gnutls_certificate_set_verify_flags(
    672 				global->xcred,
    673 				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
    674 		}
    675 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
    676 	}
    677 
    678 	if (params->client_cert && params->private_key) {
    679 		/* TODO: private_key_passwd? */
    680 		ret = gnutls_certificate_set_x509_key_file(
    681 			global->xcred, params->client_cert,
    682 			params->private_key, GNUTLS_X509_FMT_PEM);
    683 		if (ret < 0) {
    684 			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
    685 				   "in PEM format: %s", gnutls_strerror(ret));
    686 			ret = gnutls_certificate_set_x509_key_file(
    687 				global->xcred, params->client_cert,
    688 				params->private_key, GNUTLS_X509_FMT_DER);
    689 			if (ret < 0) {
    690 				wpa_printf(MSG_DEBUG, "Failed to read client "
    691 					   "cert/key in DER format: %s",
    692 					   gnutls_strerror(ret));
    693 				goto fail;
    694 			}
    695 		}
    696 	} else if (params->private_key) {
    697 		int pkcs12_ok = 0;
    698 #ifdef PKCS12_FUNCS
    699 		/* Try to load in PKCS#12 format */
    700 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
    701 		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
    702 			global->xcred, params->private_key,
    703 			GNUTLS_X509_FMT_DER, params->private_key_passwd);
    704 		if (ret != 0) {
    705 			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
    706 				   "PKCS#12 format: %s", gnutls_strerror(ret));
    707 			goto fail;
    708 		} else
    709 			pkcs12_ok = 1;
    710 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
    711 #endif /* PKCS12_FUNCS */
    712 
    713 		if (!pkcs12_ok) {
    714 			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
    715 				   "included");
    716 			goto fail;
    717 		}
    718 	}
    719 
    720 	global->params_set = 1;
    721 
    722 	return 0;
    723 
    724 fail:
    725 	gnutls_certificate_free_credentials(global->xcred);
    726 	return -1;
    727 }
    728 
    729 
    730 int tls_global_set_verify(void *ssl_ctx, int check_crl)
    731 {
    732 	/* TODO */
    733 	return 0;
    734 }
    735 
    736 
    737 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
    738 			      int verify_peer)
    739 {
    740 	if (conn == NULL || conn->session == NULL)
    741 		return -1;
    742 
    743 	conn->verify_peer = verify_peer;
    744 	gnutls_certificate_server_set_request(conn->session,
    745 					      verify_peer ? GNUTLS_CERT_REQUIRE
    746 					      : GNUTLS_CERT_REQUEST);
    747 
    748 	return 0;
    749 }
    750 
    751 
    752 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
    753 			    struct tls_keys *keys)
    754 {
    755 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
    756 	security_parameters_st *sec;
    757 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
    758 
    759 	if (conn == NULL || conn->session == NULL || keys == NULL)
    760 		return -1;
    761 
    762 	os_memset(keys, 0, sizeof(*keys));
    763 
    764 #if LIBGNUTLS_VERSION_NUMBER < 0x020c00
    765 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
    766 	sec = &conn->session->security_parameters;
    767 	keys->master_key = sec->master_secret;
    768 	keys->master_key_len = WPA_TLS_MASTER_SIZE;
    769 	keys->client_random = sec->client_random;
    770 	keys->server_random = sec->server_random;
    771 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
    772 	keys->client_random =
    773 		(u8 *) gnutls_session_get_client_random(conn->session);
    774 	keys->server_random =
    775 		(u8 *) gnutls_session_get_server_random(conn->session);
    776 	/* No access to master_secret */
    777 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
    778 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
    779 
    780 #if LIBGNUTLS_VERSION_NUMBER < 0x020c00
    781 	keys->client_random_len = WPA_TLS_RANDOM_SIZE;
    782 	keys->server_random_len = WPA_TLS_RANDOM_SIZE;
    783 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
    784 
    785 	return 0;
    786 }
    787 
    788 
    789 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
    790 		       const char *label, int server_random_first,
    791 		       u8 *out, size_t out_len)
    792 {
    793 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
    794 	if (conn == NULL || conn->session == NULL)
    795 		return -1;
    796 
    797 	return gnutls_prf(conn->session, os_strlen(label), label,
    798 			  server_random_first, 0, NULL, out_len, (char *) out);
    799 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
    800 	return -1;
    801 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
    802 }
    803 
    804 
    805 static int tls_connection_verify_peer(struct tls_connection *conn,
    806 				      gnutls_alert_description_t *err)
    807 {
    808 	unsigned int status, num_certs, i;
    809 	struct os_time now;
    810 	const gnutls_datum_t *certs;
    811 	gnutls_x509_crt_t cert;
    812 
    813 	if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
    814 		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
    815 			   "certificate chain");
    816 		*err = GNUTLS_A_INTERNAL_ERROR;
    817 		return -1;
    818 	}
    819 
    820 	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
    821 		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
    822 		*err = GNUTLS_A_INTERNAL_ERROR;
    823 		if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
    824 			wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
    825 				   "algorithm");
    826 			*err = GNUTLS_A_INSUFFICIENT_SECURITY;
    827 		}
    828 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
    829 		if (status & GNUTLS_CERT_NOT_ACTIVATED) {
    830 			wpa_printf(MSG_INFO, "TLS: Certificate not yet "
    831 				   "activated");
    832 			*err = GNUTLS_A_CERTIFICATE_EXPIRED;
    833 		}
    834 		if (status & GNUTLS_CERT_EXPIRED) {
    835 			wpa_printf(MSG_INFO, "TLS: Certificate expired");
    836 			*err = GNUTLS_A_CERTIFICATE_EXPIRED;
    837 		}
    838 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
    839 		return -1;
    840 	}
    841 
    842 	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
    843 		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
    844 			   "known issuer");
    845 		*err = GNUTLS_A_UNKNOWN_CA;
    846 		return -1;
    847 	}
    848 
    849 	if (status & GNUTLS_CERT_REVOKED) {
    850 		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
    851 		*err = GNUTLS_A_CERTIFICATE_REVOKED;
    852 		return -1;
    853 	}
    854 
    855 	os_get_time(&now);
    856 
    857 	certs = gnutls_certificate_get_peers(conn->session, &num_certs);
    858 	if (certs == NULL) {
    859 		wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
    860 			   "received");
    861 		*err = GNUTLS_A_UNKNOWN_CA;
    862 		return -1;
    863 	}
    864 
    865 	for (i = 0; i < num_certs; i++) {
    866 		char *buf;
    867 		size_t len;
    868 		if (gnutls_x509_crt_init(&cert) < 0) {
    869 			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
    870 				   "failed");
    871 			*err = GNUTLS_A_BAD_CERTIFICATE;
    872 			return -1;
    873 		}
    874 
    875 		if (gnutls_x509_crt_import(cert, &certs[i],
    876 					   GNUTLS_X509_FMT_DER) < 0) {
    877 			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
    878 				   "certificate %d/%d", i + 1, num_certs);
    879 			gnutls_x509_crt_deinit(cert);
    880 			*err = GNUTLS_A_BAD_CERTIFICATE;
    881 			return -1;
    882 		}
    883 
    884 		gnutls_x509_crt_get_dn(cert, NULL, &len);
    885 		len++;
    886 		buf = os_malloc(len + 1);
    887 		if (buf) {
    888 			buf[0] = buf[len] = '\0';
    889 			gnutls_x509_crt_get_dn(cert, buf, &len);
    890 		}
    891 		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
    892 			   i + 1, num_certs, buf);
    893 
    894 		if (i == 0) {
    895 			/* TODO: validate subject_match and altsubject_match */
    896 		}
    897 
    898 		os_free(buf);
    899 
    900 		if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
    901 		    gnutls_x509_crt_get_activation_time(cert) > now.sec) {
    902 			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
    903 				   "not valid at this time",
    904 				   i + 1, num_certs);
    905 			gnutls_x509_crt_deinit(cert);
    906 			*err = GNUTLS_A_CERTIFICATE_EXPIRED;
    907 			return -1;
    908 		}
    909 
    910 		gnutls_x509_crt_deinit(cert);
    911 	}
    912 
    913 	return 0;
    914 }
    915 
    916 
    917 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
    918 {
    919 	int res;
    920 	struct wpabuf *ad;
    921 	wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
    922 	ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
    923 	if (ad == NULL)
    924 		return NULL;
    925 
    926 	res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
    927 				 wpabuf_size(ad));
    928 	wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
    929 	if (res < 0) {
    930 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
    931 			   "(%s)", __func__, (int) res,
    932 			   gnutls_strerror(res));
    933 		wpabuf_free(ad);
    934 		return NULL;
    935 	}
    936 
    937 	wpabuf_put(ad, res);
    938 	wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
    939 		   res);
    940 	return ad;
    941 }
    942 
    943 
    944 struct wpabuf * tls_connection_handshake(void *tls_ctx,
    945 					 struct tls_connection *conn,
    946 					 const struct wpabuf *in_data,
    947 					 struct wpabuf **appl_data)
    948 {
    949 	struct tls_global *global = tls_ctx;
    950 	struct wpabuf *out_data;
    951 	int ret;
    952 
    953 	if (appl_data)
    954 		*appl_data = NULL;
    955 
    956 	if (in_data && wpabuf_len(in_data) > 0) {
    957 		if (conn->pull_buf) {
    958 			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
    959 				   "pull_buf", __func__,
    960 				   (unsigned long) wpabuf_len(conn->pull_buf));
    961 			wpabuf_free(conn->pull_buf);
    962 		}
    963 		conn->pull_buf = wpabuf_dup(in_data);
    964 		if (conn->pull_buf == NULL)
    965 			return NULL;
    966 		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
    967 	}
    968 
    969 	ret = gnutls_handshake(conn->session);
    970 	if (ret < 0) {
    971 		switch (ret) {
    972 		case GNUTLS_E_AGAIN:
    973 			if (global->server && conn->established &&
    974 			    conn->push_buf == NULL) {
    975 				/* Need to return something to trigger
    976 				 * completion of EAP-TLS. */
    977 				conn->push_buf = wpabuf_alloc(0);
    978 			}
    979 			break;
    980 		case GNUTLS_E_FATAL_ALERT_RECEIVED:
    981 			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
    982 				   __func__, gnutls_alert_get_name(
    983 					   gnutls_alert_get(conn->session)));
    984 			conn->read_alerts++;
    985 			/* continue */
    986 		default:
    987 			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
    988 				   "-> %s", __func__, gnutls_strerror(ret));
    989 			conn->failed++;
    990 		}
    991 	} else {
    992 		size_t size;
    993 		gnutls_alert_description_t err;
    994 
    995 		if (conn->verify_peer &&
    996 		    tls_connection_verify_peer(conn, &err)) {
    997 			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
    998 				   "failed validation");
    999 			conn->failed++;
   1000 			gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
   1001 			goto out;
   1002 		}
   1003 
   1004 		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
   1005 		conn->established = 1;
   1006 		if (conn->push_buf == NULL) {
   1007 			/* Need to return something to get final TLS ACK. */
   1008 			conn->push_buf = wpabuf_alloc(0);
   1009 		}
   1010 
   1011 		gnutls_session_get_data(conn->session, NULL, &size);
   1012 		if (global->session_data == NULL ||
   1013 		    global->session_data_size < size) {
   1014 			os_free(global->session_data);
   1015 			global->session_data = os_malloc(size);
   1016 		}
   1017 		if (global->session_data) {
   1018 			global->session_data_size = size;
   1019 			gnutls_session_get_data(conn->session,
   1020 						global->session_data,
   1021 						&global->session_data_size);
   1022 		}
   1023 
   1024 		if (conn->pull_buf && appl_data)
   1025 			*appl_data = gnutls_get_appl_data(conn);
   1026 	}
   1027 
   1028 out:
   1029 	out_data = conn->push_buf;
   1030 	conn->push_buf = NULL;
   1031 	return out_data;
   1032 }
   1033 
   1034 
   1035 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
   1036 						struct tls_connection *conn,
   1037 						const struct wpabuf *in_data,
   1038 						struct wpabuf **appl_data)
   1039 {
   1040 	return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
   1041 }
   1042 
   1043 
   1044 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
   1045 				       struct tls_connection *conn,
   1046 				       const struct wpabuf *in_data)
   1047 {
   1048 	ssize_t res;
   1049 	struct wpabuf *buf;
   1050 
   1051 	res = gnutls_record_send(conn->session, wpabuf_head(in_data),
   1052 				 wpabuf_len(in_data));
   1053 	if (res < 0) {
   1054 		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
   1055 			   __func__, gnutls_strerror(res));
   1056 		return NULL;
   1057 	}
   1058 
   1059 	buf = conn->push_buf;
   1060 	conn->push_buf = NULL;
   1061 	return buf;
   1062 }
   1063 
   1064 
   1065 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
   1066 				       struct tls_connection *conn,
   1067 				       const struct wpabuf *in_data)
   1068 {
   1069 	ssize_t res;
   1070 	struct wpabuf *out;
   1071 
   1072 	if (conn->pull_buf) {
   1073 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
   1074 			   "pull_buf", __func__,
   1075 			   (unsigned long) wpabuf_len(conn->pull_buf));
   1076 		wpabuf_free(conn->pull_buf);
   1077 	}
   1078 	conn->pull_buf = wpabuf_dup(in_data);
   1079 	if (conn->pull_buf == NULL)
   1080 		return NULL;
   1081 	conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
   1082 
   1083 	/*
   1084 	 * Even though we try to disable TLS compression, it is possible that
   1085 	 * this cannot be done with all TLS libraries. Add extra buffer space
   1086 	 * to handle the possibility of the decrypted data being longer than
   1087 	 * input data.
   1088 	 */
   1089 	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
   1090 	if (out == NULL)
   1091 		return NULL;
   1092 
   1093 	res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
   1094 				 wpabuf_size(out));
   1095 	if (res < 0) {
   1096 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
   1097 			   "(%s)", __func__, (int) res, gnutls_strerror(res));
   1098 		wpabuf_free(out);
   1099 		return NULL;
   1100 	}
   1101 	wpabuf_put(out, res);
   1102 
   1103 	return out;
   1104 }
   1105 
   1106 
   1107 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
   1108 {
   1109 	if (conn == NULL)
   1110 		return 0;
   1111 	return gnutls_session_is_resumed(conn->session);
   1112 }
   1113 
   1114 
   1115 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
   1116 				   u8 *ciphers)
   1117 {
   1118 	/* TODO */
   1119 	return -1;
   1120 }
   1121 
   1122 
   1123 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
   1124 		   char *buf, size_t buflen)
   1125 {
   1126 	/* TODO */
   1127 	buf[0] = '\0';
   1128 	return 0;
   1129 }
   1130 
   1131 
   1132 int tls_connection_enable_workaround(void *ssl_ctx,
   1133 				     struct tls_connection *conn)
   1134 {
   1135 	gnutls_record_disable_padding(conn->session);
   1136 	return 0;
   1137 }
   1138 
   1139 
   1140 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
   1141 				    int ext_type, const u8 *data,
   1142 				    size_t data_len)
   1143 {
   1144 	/* TODO */
   1145 	return -1;
   1146 }
   1147 
   1148 
   1149 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
   1150 {
   1151 	if (conn == NULL)
   1152 		return -1;
   1153 	return conn->failed;
   1154 }
   1155 
   1156 
   1157 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
   1158 {
   1159 	if (conn == NULL)
   1160 		return -1;
   1161 	return conn->read_alerts;
   1162 }
   1163 
   1164 
   1165 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
   1166 {
   1167 	if (conn == NULL)
   1168 		return -1;
   1169 	return conn->write_alerts;
   1170 }
   1171 
   1172 
   1173 int tls_connection_get_keyblock_size(void *tls_ctx,
   1174 				     struct tls_connection *conn)
   1175 {
   1176 	/* TODO */
   1177 	return -1;
   1178 }
   1179 
   1180 
   1181 unsigned int tls_capabilities(void *tls_ctx)
   1182 {
   1183 	return 0;
   1184 }
   1185 
   1186 
   1187 int tls_connection_set_session_ticket_cb(void *tls_ctx,
   1188 					 struct tls_connection *conn,
   1189 					 tls_session_ticket_cb cb, void *ctx)
   1190 {
   1191 	return -1;
   1192 }
   1193