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