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