2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 #include <gnutls/gnutls.h>
17 #include <gnutls/x509.h>
19 #include <gnutls/pkcs12.h>
20 #endif /* PKCS12_FUNCS */
22 #ifdef CONFIG_GNUTLS_EXTRA
23 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
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 */
38 #ifndef TLS_RANDOM_SIZE
39 #define TLS_RANDOM_SIZE 32
41 #ifndef TLS_MASTER_SIZE
42 #define TLS_MASTER_SIZE 48
46 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
47 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
48 * use of internal structures to get the master_secret and
49 * {server,client}_random.
51 #define GNUTLS_INTERNAL_STRUCTURE_HACK
52 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
55 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
57 * It looks like gnutls does not provide access to client/server_random and
58 * master_key. This is somewhat unfortunate since these are needed for key
59 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
60 * hack that copies the gnutls_session_int definition from gnutls_int.h so that
61 * we can get the needed information.
65 typedef unsigned char opaque
;
71 gnutls_connection_end_t entity
;
72 gnutls_kx_algorithm_t kx_algorithm
;
73 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm
;
74 gnutls_mac_algorithm_t read_mac_algorithm
;
75 gnutls_compression_method_t read_compression_algorithm
;
76 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm
;
77 gnutls_mac_algorithm_t write_mac_algorithm
;
78 gnutls_compression_method_t write_compression_algorithm
;
79 cipher_suite_st current_cipher_suite
;
80 opaque master_secret
[TLS_MASTER_SIZE
];
81 opaque client_random
[TLS_RANDOM_SIZE
];
82 opaque server_random
[TLS_RANDOM_SIZE
];
83 /* followed by stuff we are not interested in */
84 } security_parameters_st
;
86 struct gnutls_session_int
{
87 security_parameters_st security_parameters
;
88 /* followed by things we are not interested in */
90 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
92 static int tls_gnutls_ref_count
= 0;
95 /* Data for session resumption */
97 size_t session_data_size
;
102 gnutls_certificate_credentials_t xcred
;
105 struct tls_connection
{
106 gnutls_session session
;
107 char *subject_match
, *altsubject_match
;
108 int read_alerts
, write_alerts
, failed
;
110 u8
*pre_shared_secret
;
111 size_t pre_shared_secret_len
;
115 struct wpabuf
*push_buf
;
116 struct wpabuf
*pull_buf
;
117 const u8
*pull_buf_offset
;
120 gnutls_certificate_credentials_t xcred
;
123 int final_phase_finished
;
126 gnutls_ia_server_credentials_t iacred_srv
;
127 gnutls_ia_client_credentials_t iacred_cli
;
129 /* Session keys generated in the current phase for inner secret
130 * permutation before generating/verifying PhaseFinished. */
132 size_t session_keys_len
;
134 u8 inner_secret
[TLS_MASTER_SIZE
];
135 #endif /* GNUTLS_IA */
139 static void tls_log_func(int level
, const char *msg
)
142 if (level
== 6 || level
== 7) {
143 /* These levels seem to be mostly I/O debug and msg dumps */
152 while (*pos
!= '\0') {
159 wpa_printf(level
> 3 ? MSG_MSGDUMP
: MSG_DEBUG
,
160 "gnutls<%d> %s", level
, s
);
165 extern int wpa_debug_show_keys
;
167 void * tls_init(const struct tls_config
*conf
)
169 struct tls_global
*global
;
171 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
172 /* Because of the horrible hack to get master_secret and client/server
173 * random, we need to make sure that the gnutls version is something
174 * that is expected to have same structure definition for the session
177 const char *ok_ver
[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
181 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
183 global
= os_zalloc(sizeof(*global
));
187 if (tls_gnutls_ref_count
== 0 && gnutls_global_init() < 0) {
191 tls_gnutls_ref_count
++;
193 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
194 ver
= gnutls_check_version(NULL
);
199 wpa_printf(MSG_DEBUG
, "%s - gnutls version %s", __func__
, ver
);
200 for (i
= 0; ok_ver
[i
]; i
++) {
201 if (strcmp(ok_ver
[i
], ver
) == 0)
204 if (ok_ver
[i
] == NULL
) {
205 wpa_printf(MSG_INFO
, "Untested gnutls version %s - this needs "
206 "to be tested and enabled in tls_gnutls.c", ver
);
210 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
212 gnutls_global_set_log_function(tls_log_func
);
213 if (wpa_debug_show_keys
)
214 gnutls_global_set_log_level(11);
219 void tls_deinit(void *ssl_ctx
)
221 struct tls_global
*global
= ssl_ctx
;
223 if (global
->params_set
)
224 gnutls_certificate_free_credentials(global
->xcred
);
225 os_free(global
->session_data
);
229 tls_gnutls_ref_count
--;
230 if (tls_gnutls_ref_count
== 0)
231 gnutls_global_deinit();
235 int tls_get_errors(void *ssl_ctx
)
241 static ssize_t
tls_pull_func(gnutls_transport_ptr ptr
, void *buf
,
244 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
246 if (conn
->pull_buf
== NULL
) {
251 end
= wpabuf_head_u8(conn
->pull_buf
) + wpabuf_len(conn
->pull_buf
);
252 if ((size_t) (end
- conn
->pull_buf_offset
) < len
)
253 len
= end
- conn
->pull_buf_offset
;
254 os_memcpy(buf
, conn
->pull_buf_offset
, len
);
255 conn
->pull_buf_offset
+= len
;
256 if (conn
->pull_buf_offset
== end
) {
257 wpa_printf(MSG_DEBUG
, "%s - pull_buf consumed", __func__
);
258 wpabuf_free(conn
->pull_buf
);
259 conn
->pull_buf
= NULL
;
260 conn
->pull_buf_offset
= NULL
;
262 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in pull_buf",
264 (unsigned long) (end
- conn
->pull_buf_offset
));
270 static ssize_t
tls_push_func(gnutls_transport_ptr ptr
, const void *buf
,
273 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
275 if (wpabuf_resize(&conn
->push_buf
, len
) < 0) {
279 wpabuf_put_data(conn
->push_buf
, buf
, len
);
285 static int tls_gnutls_init_session(struct tls_global
*global
,
286 struct tls_connection
*conn
)
288 const int cert_types
[2] = { GNUTLS_CRT_X509
, 0 };
289 const int protos
[2] = { GNUTLS_TLS1
, 0 };
292 ret
= gnutls_init(&conn
->session
,
293 global
->server
? GNUTLS_SERVER
: GNUTLS_CLIENT
);
295 wpa_printf(MSG_INFO
, "TLS: Failed to initialize new TLS "
296 "connection: %s", gnutls_strerror(ret
));
300 ret
= gnutls_set_default_priority(conn
->session
);
304 ret
= gnutls_certificate_type_set_priority(conn
->session
, cert_types
);
308 ret
= gnutls_protocol_set_priority(conn
->session
, protos
);
312 gnutls_transport_set_pull_function(conn
->session
, tls_pull_func
);
313 gnutls_transport_set_push_function(conn
->session
, tls_push_func
);
314 gnutls_transport_set_ptr(conn
->session
, (gnutls_transport_ptr
) conn
);
319 wpa_printf(MSG_INFO
, "TLS: Failed to setup new TLS connection: %s",
320 gnutls_strerror(ret
));
321 gnutls_deinit(conn
->session
);
326 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
328 struct tls_global
*global
= ssl_ctx
;
329 struct tls_connection
*conn
;
332 conn
= os_zalloc(sizeof(*conn
));
336 if (tls_gnutls_init_session(global
, conn
)) {
341 if (global
->params_set
) {
342 ret
= gnutls_credentials_set(conn
->session
,
343 GNUTLS_CRD_CERTIFICATE
,
346 wpa_printf(MSG_INFO
, "Failed to configure "
347 "credentials: %s", gnutls_strerror(ret
));
353 if (gnutls_certificate_allocate_credentials(&conn
->xcred
)) {
362 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*conn
)
368 if (conn
->iacred_srv
)
369 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
370 if (conn
->iacred_cli
)
371 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
372 if (conn
->session_keys
) {
373 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
374 os_free(conn
->session_keys
);
376 #endif /* GNUTLS_IA */
378 gnutls_certificate_free_credentials(conn
->xcred
);
379 gnutls_deinit(conn
->session
);
380 os_free(conn
->pre_shared_secret
);
381 os_free(conn
->subject_match
);
382 os_free(conn
->altsubject_match
);
383 wpabuf_free(conn
->push_buf
);
384 wpabuf_free(conn
->pull_buf
);
389 int tls_connection_established(void *ssl_ctx
, struct tls_connection
*conn
)
391 return conn
? conn
->established
: 0;
395 int tls_connection_shutdown(void *ssl_ctx
, struct tls_connection
*conn
)
397 struct tls_global
*global
= ssl_ctx
;
403 /* Shutdown previous TLS connection without notifying the peer
404 * because the connection was already terminated in practice
405 * and "close notify" shutdown alert would confuse AS. */
406 gnutls_bye(conn
->session
, GNUTLS_SHUT_RDWR
);
407 wpabuf_free(conn
->push_buf
);
408 conn
->push_buf
= NULL
;
409 conn
->established
= 0;
410 conn
->final_phase_finished
= 0;
412 if (conn
->session_keys
) {
413 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
414 os_free(conn
->session_keys
);
416 conn
->session_keys_len
= 0;
417 #endif /* GNUTLS_IA */
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");
426 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
427 conn
->params_set
? conn
->xcred
:
430 wpa_printf(MSG_INFO
, "GnuTLS: Failed to configure credentials "
431 "for session resumption: %s", gnutls_strerror(ret
));
435 if (global
->session_data
) {
436 ret
= gnutls_session_set_data(conn
->session
,
437 global
->session_data
,
438 global
->session_data_size
);
440 wpa_printf(MSG_INFO
, "GnuTLS: Failed to set session "
441 "data: %s", gnutls_strerror(ret
));
451 static int tls_match_altsubject(X509
*cert
, const char *match
)
459 ext
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
461 for (i
= 0; ext
&& i
< sk_GENERAL_NAME_num(ext
); i
++) {
462 gen
= sk_GENERAL_NAME_value(ext
, i
);
475 wpa_printf(MSG_DEBUG
, "TLS: altSubjectName: "
476 "unsupported type=%d", gen
->type
);
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
);
490 snprintf(tmp
, len
, "%s:%s", field
, gen
->d
.ia5
->data
);
491 if (strstr(tmp
, match
))
502 static int tls_verify_cb(int preverify_ok
, X509_STORE_CTX
*x509_ctx
)
508 struct tls_connection
*conn
;
509 char *match
, *altmatch
;
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
));
518 conn
= SSL_get_app_data(ssl
);
519 match
= conn
? conn
->subject_match
: NULL
;
520 altmatch
= conn
? conn
->altsubject_match
: NULL
;
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
);
527 wpa_printf(MSG_DEBUG
, "TLS: tls_verify_cb - "
528 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
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
);
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
);
548 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
549 const struct tls_connection_params
*params
)
553 if (conn
== NULL
|| params
== NULL
)
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
)
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
)
572 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
573 * to force peer validation(?) */
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
);
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
);
587 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
588 "'%s' in DER format: %s",
590 gnutls_strerror(ret
));
595 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
596 gnutls_certificate_set_verify_flags(
597 conn
->xcred
, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
600 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
601 gnutls_certificate_set_verify_flags(
603 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
607 if (params
->client_cert
&& params
->private_key
) {
608 /* TODO: private_key_passwd? */
609 ret
= gnutls_certificate_set_x509_key_file(
610 conn
->xcred
, params
->client_cert
, params
->private_key
,
611 GNUTLS_X509_FMT_PEM
);
613 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
614 "in PEM format: %s", gnutls_strerror(ret
));
615 ret
= gnutls_certificate_set_x509_key_file(
616 conn
->xcred
, params
->client_cert
,
617 params
->private_key
, GNUTLS_X509_FMT_DER
);
619 wpa_printf(MSG_DEBUG
, "Failed to read client "
620 "cert/key in DER format: %s",
621 gnutls_strerror(ret
));
625 } else if (params
->private_key
) {
628 /* Try to load in PKCS#12 format */
629 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
630 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
631 conn
->xcred
, params
->private_key
, GNUTLS_X509_FMT_DER
,
632 params
->private_key_passwd
);
634 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
635 "PKCS#12 format: %s", gnutls_strerror(ret
));
639 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
640 #endif /* PKCS12_FUNCS */
643 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
649 conn
->tls_ia
= params
->tls_ia
;
650 conn
->params_set
= 1;
652 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
655 wpa_printf(MSG_INFO
, "Failed to configure credentials: %s",
656 gnutls_strerror(ret
));
660 if (conn
->iacred_cli
)
661 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
663 ret
= gnutls_ia_allocate_client_credentials(&conn
->iacred_cli
);
665 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
666 gnutls_strerror(ret
));
670 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
673 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
674 gnutls_strerror(ret
));
675 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
676 conn
->iacred_cli
= NULL
;
679 #endif /* GNUTLS_IE */
685 int tls_global_set_params(void *tls_ctx
,
686 const struct tls_connection_params
*params
)
688 struct tls_global
*global
= tls_ctx
;
691 /* Currently, global parameters are only set when running in server
695 if (global
->params_set
) {
696 gnutls_certificate_free_credentials(global
->xcred
);
697 global
->params_set
= 0;
700 ret
= gnutls_certificate_allocate_credentials(&global
->xcred
);
702 wpa_printf(MSG_DEBUG
, "Failed to allocate global credentials "
703 "%s", gnutls_strerror(ret
));
707 if (params
->ca_cert
) {
708 ret
= gnutls_certificate_set_x509_trust_file(
709 global
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_PEM
);
711 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
712 "in PEM format: %s", params
->ca_cert
,
713 gnutls_strerror(ret
));
714 ret
= gnutls_certificate_set_x509_trust_file(
715 global
->xcred
, params
->ca_cert
,
716 GNUTLS_X509_FMT_DER
);
718 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
719 "'%s' in DER format: %s",
721 gnutls_strerror(ret
));
726 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
727 gnutls_certificate_set_verify_flags(
729 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
732 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
733 gnutls_certificate_set_verify_flags(
735 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
739 if (params
->client_cert
&& params
->private_key
) {
740 /* TODO: private_key_passwd? */
741 ret
= gnutls_certificate_set_x509_key_file(
742 global
->xcred
, params
->client_cert
,
743 params
->private_key
, GNUTLS_X509_FMT_PEM
);
745 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
746 "in PEM format: %s", gnutls_strerror(ret
));
747 ret
= gnutls_certificate_set_x509_key_file(
748 global
->xcred
, params
->client_cert
,
749 params
->private_key
, GNUTLS_X509_FMT_DER
);
751 wpa_printf(MSG_DEBUG
, "Failed to read client "
752 "cert/key in DER format: %s",
753 gnutls_strerror(ret
));
757 } else if (params
->private_key
) {
760 /* Try to load in PKCS#12 format */
761 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
762 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
763 global
->xcred
, params
->private_key
,
764 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
);
766 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
767 "PKCS#12 format: %s", gnutls_strerror(ret
));
771 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
772 #endif /* PKCS12_FUNCS */
775 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
781 global
->params_set
= 1;
786 gnutls_certificate_free_credentials(global
->xcred
);
791 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
798 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
801 if (conn
== NULL
|| conn
->session
== NULL
)
804 conn
->verify_peer
= verify_peer
;
805 gnutls_certificate_server_set_request(conn
->session
,
806 verify_peer
? GNUTLS_CERT_REQUIRE
807 : GNUTLS_CERT_REQUEST
);
813 int tls_connection_get_keys(void *ssl_ctx
, struct tls_connection
*conn
,
814 struct tls_keys
*keys
)
816 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
817 security_parameters_st
*sec
;
818 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
820 if (conn
== NULL
|| conn
->session
== NULL
|| keys
== NULL
)
823 os_memset(keys
, 0, sizeof(*keys
));
825 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
826 sec
= &conn
->session
->security_parameters
;
827 keys
->master_key
= sec
->master_secret
;
828 keys
->master_key_len
= TLS_MASTER_SIZE
;
829 keys
->client_random
= sec
->client_random
;
830 keys
->server_random
= sec
->server_random
;
831 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
832 keys
->client_random
=
833 (u8
*) gnutls_session_get_client_random(conn
->session
);
834 keys
->server_random
=
835 (u8
*) gnutls_session_get_server_random(conn
->session
);
836 /* No access to master_secret */
837 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
840 gnutls_ia_extract_inner_secret(conn
->session
,
841 (char *) conn
->inner_secret
);
842 keys
->inner_secret
= conn
->inner_secret
;
843 keys
->inner_secret_len
= TLS_MASTER_SIZE
;
844 #endif /* GNUTLS_IA */
846 keys
->client_random_len
= TLS_RANDOM_SIZE
;
847 keys
->server_random_len
= TLS_RANDOM_SIZE
;
853 int tls_connection_prf(void *tls_ctx
, struct tls_connection
*conn
,
854 const char *label
, int server_random_first
,
855 u8
*out
, size_t out_len
)
857 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
858 if (conn
== NULL
|| conn
->session
== NULL
)
861 return gnutls_prf(conn
->session
, os_strlen(label
), label
,
862 server_random_first
, 0, NULL
, out_len
, (char *) out
);
863 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
865 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
869 static int tls_connection_verify_peer(struct tls_connection
*conn
,
870 gnutls_alert_description_t
*err
)
872 unsigned int status
, num_certs
, i
;
874 const gnutls_datum_t
*certs
;
875 gnutls_x509_crt_t cert
;
877 if (gnutls_certificate_verify_peers2(conn
->session
, &status
) < 0) {
878 wpa_printf(MSG_INFO
, "TLS: Failed to verify peer "
879 "certificate chain");
880 *err
= GNUTLS_A_INTERNAL_ERROR
;
884 if (conn
->verify_peer
&& (status
& GNUTLS_CERT_INVALID
)) {
885 wpa_printf(MSG_INFO
, "TLS: Peer certificate not trusted");
886 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
) {
887 wpa_printf(MSG_INFO
, "TLS: Certificate uses insecure "
889 *err
= GNUTLS_A_INSUFFICIENT_SECURITY
;
891 if (status
& GNUTLS_CERT_NOT_ACTIVATED
) {
892 wpa_printf(MSG_INFO
, "TLS: Certificate not yet "
894 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
896 if (status
& GNUTLS_CERT_EXPIRED
) {
897 wpa_printf(MSG_INFO
, "TLS: Certificate expired");
898 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
903 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
) {
904 wpa_printf(MSG_INFO
, "TLS: Peer certificate does not have a "
906 *err
= GNUTLS_A_UNKNOWN_CA
;
910 if (status
& GNUTLS_CERT_REVOKED
) {
911 wpa_printf(MSG_INFO
, "TLS: Peer certificate has been revoked");
912 *err
= GNUTLS_A_CERTIFICATE_REVOKED
;
918 certs
= gnutls_certificate_get_peers(conn
->session
, &num_certs
);
920 wpa_printf(MSG_INFO
, "TLS: No peer certificate chain "
922 *err
= GNUTLS_A_UNKNOWN_CA
;
926 for (i
= 0; i
< num_certs
; i
++) {
929 if (gnutls_x509_crt_init(&cert
) < 0) {
930 wpa_printf(MSG_INFO
, "TLS: Certificate initialization "
932 *err
= GNUTLS_A_BAD_CERTIFICATE
;
936 if (gnutls_x509_crt_import(cert
, &certs
[i
],
937 GNUTLS_X509_FMT_DER
) < 0) {
938 wpa_printf(MSG_INFO
, "TLS: Could not parse peer "
939 "certificate %d/%d", i
+ 1, num_certs
);
940 gnutls_x509_crt_deinit(cert
);
941 *err
= GNUTLS_A_BAD_CERTIFICATE
;
945 gnutls_x509_crt_get_dn(cert
, NULL
, &len
);
947 buf
= os_malloc(len
+ 1);
949 buf
[0] = buf
[len
] = '\0';
950 gnutls_x509_crt_get_dn(cert
, buf
, &len
);
952 wpa_printf(MSG_DEBUG
, "TLS: Peer cert chain %d/%d: %s",
953 i
+ 1, num_certs
, buf
);
956 /* TODO: validate subject_match and altsubject_match */
961 if (gnutls_x509_crt_get_expiration_time(cert
) < now
.sec
||
962 gnutls_x509_crt_get_activation_time(cert
) > now
.sec
) {
963 wpa_printf(MSG_INFO
, "TLS: Peer certificate %d/%d is "
964 "not valid at this time",
966 gnutls_x509_crt_deinit(cert
);
967 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
971 gnutls_x509_crt_deinit(cert
);
978 static struct wpabuf
* gnutls_get_appl_data(struct tls_connection
*conn
)
982 wpa_printf(MSG_DEBUG
, "GnuTLS: Check for possible Application Data");
983 ad
= wpabuf_alloc((wpabuf_len(conn
->pull_buf
) + 500) * 3);
987 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(ad
),
989 wpa_printf(MSG_DEBUG
, "GnuTLS: gnutls_record_recv: %d", res
);
991 wpa_printf(MSG_DEBUG
, "%s - gnutls_ia_recv failed: %d "
992 "(%s)", __func__
, (int) res
,
993 gnutls_strerror(res
));
999 wpa_printf(MSG_DEBUG
, "GnuTLS: Received %d bytes of Application Data",
1005 struct wpabuf
* tls_connection_handshake(void *tls_ctx
,
1006 struct tls_connection
*conn
,
1007 const struct wpabuf
*in_data
,
1008 struct wpabuf
**appl_data
)
1010 struct tls_global
*global
= tls_ctx
;
1011 struct wpabuf
*out_data
;
1017 if (in_data
&& wpabuf_len(in_data
) > 0) {
1018 if (conn
->pull_buf
) {
1019 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1020 "pull_buf", __func__
,
1021 (unsigned long) wpabuf_len(conn
->pull_buf
));
1022 wpabuf_free(conn
->pull_buf
);
1024 conn
->pull_buf
= wpabuf_dup(in_data
);
1025 if (conn
->pull_buf
== NULL
)
1027 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1030 ret
= gnutls_handshake(conn
->session
);
1033 case GNUTLS_E_AGAIN
:
1034 if (global
->server
&& conn
->established
&&
1035 conn
->push_buf
== NULL
) {
1036 /* Need to return something to trigger
1037 * completion of EAP-TLS. */
1038 conn
->push_buf
= wpabuf_alloc(0);
1041 case GNUTLS_E_FATAL_ALERT_RECEIVED
:
1042 wpa_printf(MSG_DEBUG
, "%s - received fatal '%s' alert",
1043 __func__
, gnutls_alert_get_name(
1044 gnutls_alert_get(conn
->session
)));
1045 conn
->read_alerts
++;
1048 wpa_printf(MSG_DEBUG
, "%s - gnutls_handshake failed "
1049 "-> %s", __func__
, gnutls_strerror(ret
));
1054 gnutls_alert_description_t err
;
1056 if (conn
->verify_peer
&&
1057 tls_connection_verify_peer(conn
, &err
)) {
1058 wpa_printf(MSG_INFO
, "TLS: Peer certificate chain "
1059 "failed validation");
1061 gnutls_alert_send(conn
->session
, GNUTLS_AL_FATAL
, err
);
1065 #ifdef CONFIG_GNUTLS_EXTRA
1066 if (conn
->tls_ia
&& !gnutls_ia_handshake_p(conn
->session
)) {
1067 wpa_printf(MSG_INFO
, "TLS: No TLS/IA negotiation");
1071 #endif /* CONFIG_GNUTLS_EXTRA */
1074 wpa_printf(MSG_DEBUG
, "TLS: Start TLS/IA handshake");
1076 wpa_printf(MSG_DEBUG
, "TLS: Handshake completed "
1079 conn
->established
= 1;
1080 if (conn
->push_buf
== NULL
) {
1081 /* Need to return something to get final TLS ACK. */
1082 conn
->push_buf
= wpabuf_alloc(0);
1085 gnutls_session_get_data(conn
->session
, NULL
, &size
);
1086 if (global
->session_data
== NULL
||
1087 global
->session_data_size
< size
) {
1088 os_free(global
->session_data
);
1089 global
->session_data
= os_malloc(size
);
1091 if (global
->session_data
) {
1092 global
->session_data_size
= size
;
1093 gnutls_session_get_data(conn
->session
,
1094 global
->session_data
,
1095 &global
->session_data_size
);
1098 if (conn
->pull_buf
&& appl_data
)
1099 *appl_data
= gnutls_get_appl_data(conn
);
1103 out_data
= conn
->push_buf
;
1104 conn
->push_buf
= NULL
;
1109 struct wpabuf
* tls_connection_server_handshake(void *tls_ctx
,
1110 struct tls_connection
*conn
,
1111 const struct wpabuf
*in_data
,
1112 struct wpabuf
**appl_data
)
1114 return tls_connection_handshake(tls_ctx
, conn
, in_data
, appl_data
);
1118 struct wpabuf
* tls_connection_encrypt(void *tls_ctx
,
1119 struct tls_connection
*conn
,
1120 const struct wpabuf
*in_data
)
1127 res
= gnutls_ia_send(conn
->session
, wpabuf_head(in_data
),
1128 wpabuf_len(in_data
));
1130 #endif /* GNUTLS_IA */
1131 res
= gnutls_record_send(conn
->session
, wpabuf_head(in_data
),
1132 wpabuf_len(in_data
));
1134 wpa_printf(MSG_INFO
, "%s: Encryption failed: %s",
1135 __func__
, gnutls_strerror(res
));
1139 buf
= conn
->push_buf
;
1140 conn
->push_buf
= NULL
;
1145 struct wpabuf
* tls_connection_decrypt(void *tls_ctx
,
1146 struct tls_connection
*conn
,
1147 const struct wpabuf
*in_data
)
1152 if (conn
->pull_buf
) {
1153 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1154 "pull_buf", __func__
,
1155 (unsigned long) wpabuf_len(conn
->pull_buf
));
1156 wpabuf_free(conn
->pull_buf
);
1158 conn
->pull_buf
= wpabuf_dup(in_data
);
1159 if (conn
->pull_buf
== NULL
)
1161 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1164 * Even though we try to disable TLS compression, it is possible that
1165 * this cannot be done with all TLS libraries. Add extra buffer space
1166 * to handle the possibility of the decrypted data being longer than
1169 out
= wpabuf_alloc((wpabuf_len(in_data
) + 500) * 3);
1175 res
= gnutls_ia_recv(conn
->session
, wpabuf_mhead(out
),
1177 if (res
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
||
1178 res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
) {
1179 int final
= res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
;
1180 wpa_printf(MSG_DEBUG
, "%s: Received %sPhaseFinished",
1181 __func__
, final
? "Final" : "Intermediate");
1183 res
= gnutls_ia_permute_inner_secret(
1184 conn
->session
, conn
->session_keys_len
,
1185 (char *) conn
->session_keys
);
1186 if (conn
->session_keys
) {
1187 os_memset(conn
->session_keys
, 0,
1188 conn
->session_keys_len
);
1189 os_free(conn
->session_keys
);
1191 conn
->session_keys
= NULL
;
1192 conn
->session_keys_len
= 0;
1194 wpa_printf(MSG_DEBUG
, "%s: Failed to permute "
1196 __func__
, gnutls_strerror(res
));
1201 res
= gnutls_ia_verify_endphase(conn
->session
,
1204 wpa_printf(MSG_DEBUG
, "%s: Correct endphase "
1205 "checksum", __func__
);
1207 wpa_printf(MSG_INFO
, "%s: Endphase "
1208 "verification failed: %s",
1209 __func__
, gnutls_strerror(res
));
1215 conn
->final_phase_finished
= 1;
1221 wpa_printf(MSG_DEBUG
, "%s - gnutls_ia_recv failed: %d "
1222 "(%s)", __func__
, (int) res
,
1223 gnutls_strerror(res
));
1227 wpabuf_put(out
, res
);
1230 #endif /* GNUTLS_IA */
1232 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(out
),
1235 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1236 "(%s)", __func__
, (int) res
, gnutls_strerror(res
));
1240 wpabuf_put(out
, res
);
1246 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
1250 return gnutls_session_is_resumed(conn
->session
);
1254 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
1262 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
1263 char *buf
, size_t buflen
)
1271 int tls_connection_enable_workaround(void *ssl_ctx
,
1272 struct tls_connection
*conn
)
1274 gnutls_record_disable_padding(conn
->session
);
1279 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
1280 int ext_type
, const u8
*data
,
1288 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
1292 return conn
->failed
;
1296 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1300 return conn
->read_alerts
;
1304 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1308 return conn
->write_alerts
;
1312 int tls_connection_get_keyblock_size(void *tls_ctx
,
1313 struct tls_connection
*conn
)
1320 unsigned int tls_capabilities(void *tls_ctx
)
1322 unsigned int capa
= 0;
1325 capa
|= TLS_CAPABILITY_IA
;
1326 #endif /* GNUTLS_IA */
1332 int tls_connection_set_ia(void *tls_ctx
, struct tls_connection
*conn
,
1341 conn
->tls_ia
= tls_ia
;
1345 ret
= gnutls_ia_allocate_server_credentials(&conn
->iacred_srv
);
1347 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
1348 gnutls_strerror(ret
));
1352 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
1355 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
1356 gnutls_strerror(ret
));
1357 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
1358 conn
->iacred_srv
= NULL
;
1363 #else /* GNUTLS_IA */
1365 #endif /* GNUTLS_IA */
1369 struct wpabuf
* tls_connection_ia_send_phase_finished(
1370 void *tls_ctx
, struct tls_connection
*conn
, int final
)
1376 if (conn
== NULL
|| conn
->session
== NULL
|| !conn
->tls_ia
)
1379 ret
= gnutls_ia_permute_inner_secret(conn
->session
,
1380 conn
->session_keys_len
,
1381 (char *) conn
->session_keys
);
1382 if (conn
->session_keys
) {
1383 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1384 os_free(conn
->session_keys
);
1386 conn
->session_keys
= NULL
;
1387 conn
->session_keys_len
= 0;
1389 wpa_printf(MSG_DEBUG
, "%s: Failed to permute inner secret: %s",
1390 __func__
, gnutls_strerror(ret
));
1394 ret
= gnutls_ia_endphase_send(conn
->session
, final
);
1396 wpa_printf(MSG_DEBUG
, "%s: Failed to send endphase: %s",
1397 __func__
, gnutls_strerror(ret
));
1401 buf
= conn
->push_buf
;
1402 conn
->push_buf
= NULL
;
1404 #else /* GNUTLS_IA */
1406 #endif /* GNUTLS_IA */
1410 int tls_connection_ia_final_phase_finished(void *tls_ctx
,
1411 struct tls_connection
*conn
)
1416 return conn
->final_phase_finished
;
1420 int tls_connection_ia_permute_inner_secret(void *tls_ctx
,
1421 struct tls_connection
*conn
,
1422 const u8
*key
, size_t key_len
)
1425 if (conn
== NULL
|| !conn
->tls_ia
)
1428 if (conn
->session_keys
) {
1429 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1430 os_free(conn
->session_keys
);
1432 conn
->session_keys_len
= 0;
1435 conn
->session_keys
= os_malloc(key_len
);
1436 if (conn
->session_keys
== NULL
)
1438 os_memcpy(conn
->session_keys
, key
, key_len
);
1439 conn
->session_keys_len
= key_len
;
1441 conn
->session_keys
= NULL
;
1442 conn
->session_keys_len
= 0;
1446 #else /* GNUTLS_IA */
1448 #endif /* GNUTLS_IA */
1452 int tls_connection_set_session_ticket_cb(void *tls_ctx
,
1453 struct tls_connection
*conn
,
1454 tls_session_ticket_cb cb
, void *ctx
)