2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
13 #include <gnutls/pkcs12.h>
14 #endif /* PKCS12_FUNCS */
15 #if GNUTLS_VERSION_NUMBER >= 0x030103
16 #include <gnutls/ocsp.h>
20 #include "crypto/crypto.h"
24 static int tls_gnutls_ref_count
= 0;
27 /* Data for session resumption */
29 size_t session_data_size
;
34 gnutls_certificate_credentials_t xcred
;
36 void (*event_cb
)(void *ctx
, enum tls_event ev
,
37 union tls_event_data
*data
);
41 char *ocsp_stapling_response
;
44 struct tls_connection
{
45 struct tls_global
*global
;
46 gnutls_session_t session
;
47 int read_alerts
, write_alerts
, failed
;
49 u8
*pre_shared_secret
;
50 size_t pre_shared_secret_len
;
53 unsigned int disable_time_checks
:1;
55 struct wpabuf
*push_buf
;
56 struct wpabuf
*pull_buf
;
57 const u8
*pull_buf_offset
;
60 gnutls_certificate_credentials_t xcred
;
68 static int tls_connection_verify_peer(gnutls_session_t session
);
71 static void tls_log_func(int level
, const char *msg
)
74 if (level
== 6 || level
== 7) {
75 /* These levels seem to be mostly I/O debug and msg dumps */
84 while (*pos
!= '\0') {
91 wpa_printf(level
> 3 ? MSG_MSGDUMP
: MSG_DEBUG
,
92 "gnutls<%d> %s", level
, s
);
97 void * tls_init(const struct tls_config
*conf
)
99 struct tls_global
*global
;
101 if (tls_gnutls_ref_count
== 0) {
102 wpa_printf(MSG_DEBUG
,
103 "GnuTLS: Library version %s (runtime) - %s (build)",
104 gnutls_check_version(NULL
), GNUTLS_VERSION
);
107 global
= os_zalloc(sizeof(*global
));
111 if (tls_gnutls_ref_count
== 0 && gnutls_global_init() < 0) {
115 tls_gnutls_ref_count
++;
117 gnutls_global_set_log_function(tls_log_func
);
118 if (wpa_debug_show_keys
)
119 gnutls_global_set_log_level(11);
122 global
->event_cb
= conf
->event_cb
;
123 global
->cb_ctx
= conf
->cb_ctx
;
124 global
->cert_in_cb
= conf
->cert_in_cb
;
131 void tls_deinit(void *ssl_ctx
)
133 struct tls_global
*global
= ssl_ctx
;
135 if (global
->params_set
)
136 gnutls_certificate_free_credentials(global
->xcred
);
137 os_free(global
->session_data
);
138 os_free(global
->ocsp_stapling_response
);
142 tls_gnutls_ref_count
--;
143 if (tls_gnutls_ref_count
== 0)
144 gnutls_global_deinit();
148 int tls_get_errors(void *ssl_ctx
)
154 static ssize_t
tls_pull_func(gnutls_transport_ptr_t ptr
, void *buf
,
157 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
159 if (conn
->pull_buf
== NULL
) {
164 end
= wpabuf_head_u8(conn
->pull_buf
) + wpabuf_len(conn
->pull_buf
);
165 if ((size_t) (end
- conn
->pull_buf_offset
) < len
)
166 len
= end
- conn
->pull_buf_offset
;
167 os_memcpy(buf
, conn
->pull_buf_offset
, len
);
168 conn
->pull_buf_offset
+= len
;
169 if (conn
->pull_buf_offset
== end
) {
170 wpa_printf(MSG_DEBUG
, "%s - pull_buf consumed", __func__
);
171 wpabuf_free(conn
->pull_buf
);
172 conn
->pull_buf
= NULL
;
173 conn
->pull_buf_offset
= NULL
;
175 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in pull_buf",
177 (unsigned long) (end
- conn
->pull_buf_offset
));
183 static ssize_t
tls_push_func(gnutls_transport_ptr_t ptr
, const void *buf
,
186 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
188 if (wpabuf_resize(&conn
->push_buf
, len
) < 0) {
192 wpabuf_put_data(conn
->push_buf
, buf
, len
);
198 static int tls_gnutls_init_session(struct tls_global
*global
,
199 struct tls_connection
*conn
)
204 ret
= gnutls_init(&conn
->session
,
205 global
->server
? GNUTLS_SERVER
: GNUTLS_CLIENT
);
207 wpa_printf(MSG_INFO
, "TLS: Failed to initialize new TLS "
208 "connection: %s", gnutls_strerror(ret
));
212 ret
= gnutls_set_default_priority(conn
->session
);
216 ret
= gnutls_priority_set_direct(conn
->session
, "NORMAL:-VERS-SSL3.0",
219 wpa_printf(MSG_ERROR
, "GnuTLS: Priority string failure at "
224 gnutls_transport_set_pull_function(conn
->session
, tls_pull_func
);
225 gnutls_transport_set_push_function(conn
->session
, tls_push_func
);
226 gnutls_transport_set_ptr(conn
->session
, (gnutls_transport_ptr_t
) conn
);
227 gnutls_session_set_ptr(conn
->session
, conn
);
232 wpa_printf(MSG_INFO
, "TLS: Failed to setup new TLS connection: %s",
233 gnutls_strerror(ret
));
234 gnutls_deinit(conn
->session
);
239 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
241 struct tls_global
*global
= ssl_ctx
;
242 struct tls_connection
*conn
;
245 conn
= os_zalloc(sizeof(*conn
));
248 conn
->global
= global
;
250 if (tls_gnutls_init_session(global
, conn
)) {
255 if (global
->params_set
) {
256 ret
= gnutls_credentials_set(conn
->session
,
257 GNUTLS_CRD_CERTIFICATE
,
260 wpa_printf(MSG_INFO
, "Failed to configure "
261 "credentials: %s", gnutls_strerror(ret
));
267 if (gnutls_certificate_allocate_credentials(&conn
->xcred
)) {
276 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*conn
)
281 gnutls_certificate_free_credentials(conn
->xcred
);
282 gnutls_deinit(conn
->session
);
283 os_free(conn
->pre_shared_secret
);
284 wpabuf_free(conn
->push_buf
);
285 wpabuf_free(conn
->pull_buf
);
286 os_free(conn
->suffix_match
);
287 os_free(conn
->domain_match
);
292 int tls_connection_established(void *ssl_ctx
, struct tls_connection
*conn
)
294 return conn
? conn
->established
: 0;
298 int tls_connection_shutdown(void *ssl_ctx
, struct tls_connection
*conn
)
300 struct tls_global
*global
= ssl_ctx
;
306 /* Shutdown previous TLS connection without notifying the peer
307 * because the connection was already terminated in practice
308 * and "close notify" shutdown alert would confuse AS. */
309 gnutls_bye(conn
->session
, GNUTLS_SHUT_RDWR
);
310 wpabuf_free(conn
->push_buf
);
311 conn
->push_buf
= NULL
;
312 conn
->established
= 0;
314 gnutls_deinit(conn
->session
);
315 if (tls_gnutls_init_session(global
, conn
)) {
316 wpa_printf(MSG_INFO
, "GnuTLS: Failed to preparare new session "
317 "for session resumption use");
321 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
322 conn
->params_set
? conn
->xcred
:
325 wpa_printf(MSG_INFO
, "GnuTLS: Failed to configure credentials "
326 "for session resumption: %s", gnutls_strerror(ret
));
330 if (global
->session_data
) {
331 ret
= gnutls_session_set_data(conn
->session
,
332 global
->session_data
,
333 global
->session_data_size
);
335 wpa_printf(MSG_INFO
, "GnuTLS: Failed to set session "
336 "data: %s", gnutls_strerror(ret
));
345 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
346 const struct tls_connection_params
*params
)
350 if (conn
== NULL
|| params
== NULL
)
353 if (params
->flags
& TLS_CONN_REQUIRE_OCSP_ALL
) {
355 "GnuTLS: ocsp=3 not supported");
359 if (params
->flags
& TLS_CONN_EXT_CERT_CHECK
) {
361 "GnuTLS: tls_ext_cert_check=1 not supported");
365 if (params
->subject_match
) {
366 wpa_printf(MSG_INFO
, "GnuTLS: subject_match not supported");
370 if (params
->altsubject_match
) {
371 wpa_printf(MSG_INFO
, "GnuTLS: altsubject_match not supported");
375 os_free(conn
->suffix_match
);
376 conn
->suffix_match
= NULL
;
377 if (params
->suffix_match
) {
378 conn
->suffix_match
= os_strdup(params
->suffix_match
);
379 if (conn
->suffix_match
== NULL
)
383 #if GNUTLS_VERSION_NUMBER >= 0x030300
384 os_free(conn
->domain_match
);
385 conn
->domain_match
= NULL
;
386 if (params
->domain_match
) {
387 conn
->domain_match
= os_strdup(params
->domain_match
);
388 if (conn
->domain_match
== NULL
)
392 if (params
->domain_match
) {
393 wpa_printf(MSG_INFO
, "GnuTLS: domain_match not supported");
396 #endif /* >= 3.3.0 */
398 conn
->flags
= params
->flags
;
400 if (params
->openssl_ciphers
) {
401 wpa_printf(MSG_INFO
, "GnuTLS: openssl_ciphers not supported");
405 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
406 * to force peer validation(?) */
408 if (params
->ca_cert
) {
409 wpa_printf(MSG_DEBUG
, "GnuTLS: Try to parse %s in DER format",
411 ret
= gnutls_certificate_set_x509_trust_file(
412 conn
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_DER
);
414 wpa_printf(MSG_DEBUG
,
415 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
417 gnutls_strerror(ret
));
418 ret
= gnutls_certificate_set_x509_trust_file(
419 conn
->xcred
, params
->ca_cert
,
420 GNUTLS_X509_FMT_PEM
);
422 wpa_printf(MSG_DEBUG
,
423 "Failed to read CA cert '%s' in PEM format: %s",
425 gnutls_strerror(ret
));
429 } else if (params
->ca_cert_blob
) {
432 ca
.data
= (unsigned char *) params
->ca_cert_blob
;
433 ca
.size
= params
->ca_cert_blob_len
;
435 ret
= gnutls_certificate_set_x509_trust_mem(
436 conn
->xcred
, &ca
, GNUTLS_X509_FMT_DER
);
438 wpa_printf(MSG_DEBUG
,
439 "Failed to parse CA cert in DER format: %s",
440 gnutls_strerror(ret
));
441 ret
= gnutls_certificate_set_x509_trust_mem(
442 conn
->xcred
, &ca
, GNUTLS_X509_FMT_PEM
);
444 wpa_printf(MSG_DEBUG
,
445 "Failed to parse CA cert in PEM format: %s",
446 gnutls_strerror(ret
));
450 } else if (params
->ca_path
) {
451 wpa_printf(MSG_INFO
, "GnuTLS: ca_path not supported");
455 conn
->disable_time_checks
= 0;
456 if (params
->ca_cert
|| params
->ca_cert_blob
) {
457 conn
->verify_peer
= 1;
458 gnutls_certificate_set_verify_function(
459 conn
->xcred
, tls_connection_verify_peer
);
461 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
462 gnutls_certificate_set_verify_flags(
463 conn
->xcred
, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
466 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
467 conn
->disable_time_checks
= 1;
468 gnutls_certificate_set_verify_flags(
470 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
474 if (params
->client_cert
&& params
->private_key
) {
475 #if GNUTLS_VERSION_NUMBER >= 0x03010b
476 ret
= gnutls_certificate_set_x509_key_file2(
477 conn
->xcred
, params
->client_cert
, params
->private_key
,
478 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
, 0);
480 /* private_key_passwd not (easily) supported here */
481 ret
= gnutls_certificate_set_x509_key_file(
482 conn
->xcred
, params
->client_cert
, params
->private_key
,
483 GNUTLS_X509_FMT_DER
);
486 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
487 "in DER format: %s", gnutls_strerror(ret
));
488 #if GNUTLS_VERSION_NUMBER >= 0x03010b
489 ret
= gnutls_certificate_set_x509_key_file2(
490 conn
->xcred
, params
->client_cert
,
491 params
->private_key
, GNUTLS_X509_FMT_PEM
,
492 params
->private_key_passwd
, 0);
494 ret
= gnutls_certificate_set_x509_key_file(
495 conn
->xcred
, params
->client_cert
,
496 params
->private_key
, GNUTLS_X509_FMT_PEM
);
499 wpa_printf(MSG_DEBUG
, "Failed to read client "
500 "cert/key in PEM format: %s",
501 gnutls_strerror(ret
));
505 } else if (params
->private_key
) {
508 /* Try to load in PKCS#12 format */
509 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
510 conn
->xcred
, params
->private_key
, GNUTLS_X509_FMT_DER
,
511 params
->private_key_passwd
);
513 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
514 "PKCS#12 format: %s", gnutls_strerror(ret
));
518 #endif /* PKCS12_FUNCS */
521 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
525 } else if (params
->client_cert_blob
&& params
->private_key_blob
) {
526 gnutls_datum_t cert
, key
;
528 cert
.data
= (unsigned char *) params
->client_cert_blob
;
529 cert
.size
= params
->client_cert_blob_len
;
530 key
.data
= (unsigned char *) params
->private_key_blob
;
531 key
.size
= params
->private_key_blob_len
;
533 #if GNUTLS_VERSION_NUMBER >= 0x03010b
534 ret
= gnutls_certificate_set_x509_key_mem2(
535 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_DER
,
536 params
->private_key_passwd
, 0);
538 /* private_key_passwd not (easily) supported here */
539 ret
= gnutls_certificate_set_x509_key_mem(
540 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_DER
);
543 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
544 "in DER format: %s", gnutls_strerror(ret
));
545 #if GNUTLS_VERSION_NUMBER >= 0x03010b
546 ret
= gnutls_certificate_set_x509_key_mem2(
547 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_PEM
,
548 params
->private_key_passwd
, 0);
550 /* private_key_passwd not (easily) supported here */
551 ret
= gnutls_certificate_set_x509_key_mem(
552 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_PEM
);
555 wpa_printf(MSG_DEBUG
, "Failed to read client "
556 "cert/key in PEM format: %s",
557 gnutls_strerror(ret
));
561 } else if (params
->private_key_blob
) {
565 key
.data
= (unsigned char *) params
->private_key_blob
;
566 key
.size
= params
->private_key_blob_len
;
568 /* Try to load in PKCS#12 format */
569 ret
= gnutls_certificate_set_x509_simple_pkcs12_mem(
570 conn
->xcred
, &key
, GNUTLS_X509_FMT_DER
,
571 params
->private_key_passwd
);
573 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
574 "PKCS#12 format: %s", gnutls_strerror(ret
));
577 #else /* PKCS12_FUNCS */
578 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not included");
580 #endif /* PKCS12_FUNCS */
583 #if GNUTLS_VERSION_NUMBER >= 0x030103
584 if (params
->flags
& (TLS_CONN_REQUEST_OCSP
| TLS_CONN_REQUIRE_OCSP
)) {
585 ret
= gnutls_ocsp_status_request_enable_client(conn
->session
,
587 if (ret
!= GNUTLS_E_SUCCESS
) {
589 "GnuTLS: Failed to enable OCSP client");
594 if (params
->flags
& TLS_CONN_REQUIRE_OCSP
) {
596 "GnuTLS: OCSP not supported by this version of GnuTLS");
601 conn
->params_set
= 1;
603 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
606 wpa_printf(MSG_INFO
, "Failed to configure credentials: %s",
607 gnutls_strerror(ret
));
614 #if GNUTLS_VERSION_NUMBER >= 0x030103
615 static int server_ocsp_status_req(gnutls_session_t session
, void *ptr
,
616 gnutls_datum_t
*resp
)
618 struct tls_global
*global
= ptr
;
622 if (!global
->ocsp_stapling_response
) {
623 wpa_printf(MSG_DEBUG
, "GnuTLS: OCSP status callback - no response configured");
624 return GNUTLS_E_NO_CERTIFICATE_STATUS
;
627 cached
= os_readfile(global
->ocsp_stapling_response
, &len
);
629 wpa_printf(MSG_DEBUG
,
630 "GnuTLS: OCSP status callback - could not read response file (%s)",
631 global
->ocsp_stapling_response
);
632 return GNUTLS_E_NO_CERTIFICATE_STATUS
;
635 wpa_printf(MSG_DEBUG
,
636 "GnuTLS: OCSP status callback - send cached response");
637 resp
->data
= gnutls_malloc(len
);
640 return GNUTLS_E_MEMORY_ERROR
;
643 os_memcpy(resp
->data
, cached
, len
);
647 return GNUTLS_E_SUCCESS
;
652 int tls_global_set_params(void *tls_ctx
,
653 const struct tls_connection_params
*params
)
655 struct tls_global
*global
= tls_ctx
;
658 /* Currently, global parameters are only set when running in server
662 if (global
->params_set
) {
663 gnutls_certificate_free_credentials(global
->xcred
);
664 global
->params_set
= 0;
667 ret
= gnutls_certificate_allocate_credentials(&global
->xcred
);
669 wpa_printf(MSG_DEBUG
, "Failed to allocate global credentials "
670 "%s", gnutls_strerror(ret
));
674 if (params
->ca_cert
) {
675 ret
= gnutls_certificate_set_x509_trust_file(
676 global
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_DER
);
678 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
679 "in DER format: %s", params
->ca_cert
,
680 gnutls_strerror(ret
));
681 ret
= gnutls_certificate_set_x509_trust_file(
682 global
->xcred
, params
->ca_cert
,
683 GNUTLS_X509_FMT_PEM
);
685 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
686 "'%s' in PEM format: %s",
688 gnutls_strerror(ret
));
693 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
694 gnutls_certificate_set_verify_flags(
696 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
699 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
700 gnutls_certificate_set_verify_flags(
702 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
706 if (params
->client_cert
&& params
->private_key
) {
707 /* TODO: private_key_passwd? */
708 ret
= gnutls_certificate_set_x509_key_file(
709 global
->xcred
, params
->client_cert
,
710 params
->private_key
, GNUTLS_X509_FMT_DER
);
712 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
713 "in DER format: %s", gnutls_strerror(ret
));
714 ret
= gnutls_certificate_set_x509_key_file(
715 global
->xcred
, params
->client_cert
,
716 params
->private_key
, GNUTLS_X509_FMT_PEM
);
718 wpa_printf(MSG_DEBUG
, "Failed to read client "
719 "cert/key in PEM format: %s",
720 gnutls_strerror(ret
));
724 } else if (params
->private_key
) {
727 /* Try to load in PKCS#12 format */
728 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
729 global
->xcred
, params
->private_key
,
730 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
);
732 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
733 "PKCS#12 format: %s", gnutls_strerror(ret
));
737 #endif /* PKCS12_FUNCS */
740 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
746 #if GNUTLS_VERSION_NUMBER >= 0x030103
747 os_free(global
->ocsp_stapling_response
);
748 if (params
->ocsp_stapling_response
)
749 global
->ocsp_stapling_response
=
750 os_strdup(params
->ocsp_stapling_response
);
752 global
->ocsp_stapling_response
= NULL
;
753 gnutls_certificate_set_ocsp_status_request_function(
754 global
->xcred
, server_ocsp_status_req
, global
);
757 global
->params_set
= 1;
762 gnutls_certificate_free_credentials(global
->xcred
);
767 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
774 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
775 int verify_peer
, unsigned int flags
,
776 const u8
*session_ctx
, size_t session_ctx_len
)
778 if (conn
== NULL
|| conn
->session
== NULL
)
781 conn
->verify_peer
= verify_peer
;
782 gnutls_certificate_server_set_request(conn
->session
,
783 verify_peer
? GNUTLS_CERT_REQUIRE
784 : GNUTLS_CERT_REQUEST
);
790 int tls_connection_get_random(void *ssl_ctx
, struct tls_connection
*conn
,
791 struct tls_random
*keys
)
793 #if GNUTLS_VERSION_NUMBER >= 0x030012
794 gnutls_datum_t client
, server
;
796 if (conn
== NULL
|| conn
->session
== NULL
|| keys
== NULL
)
799 os_memset(keys
, 0, sizeof(*keys
));
800 gnutls_session_get_random(conn
->session
, &client
, &server
);
801 keys
->client_random
= client
.data
;
802 keys
->server_random
= server
.data
;
803 keys
->client_random_len
= client
.size
;
804 keys
->server_random_len
= client
.size
;
813 int tls_connection_export_key(void *tls_ctx
, struct tls_connection
*conn
,
814 const char *label
, u8
*out
, size_t out_len
)
816 if (conn
== NULL
|| conn
->session
== NULL
)
819 return gnutls_prf(conn
->session
, os_strlen(label
), label
,
820 0 /* client_random first */, 0, NULL
, out_len
,
825 int tls_connection_get_eap_fast_key(void *tls_ctx
, struct tls_connection
*conn
,
826 u8
*out
, size_t out_len
)
832 static void gnutls_tls_fail_event(struct tls_connection
*conn
,
833 const gnutls_datum_t
*cert
, int depth
,
834 const char *subject
, const char *err_str
,
835 enum tls_fail_reason reason
)
837 union tls_event_data ev
;
838 struct tls_global
*global
= conn
->global
;
839 struct wpabuf
*cert_buf
= NULL
;
841 if (global
->event_cb
== NULL
)
844 os_memset(&ev
, 0, sizeof(ev
));
845 ev
.cert_fail
.depth
= depth
;
846 ev
.cert_fail
.subject
= subject
? subject
: "";
847 ev
.cert_fail
.reason
= reason
;
848 ev
.cert_fail
.reason_txt
= err_str
;
850 cert_buf
= wpabuf_alloc_copy(cert
->data
, cert
->size
);
851 ev
.cert_fail
.cert
= cert_buf
;
853 global
->event_cb(global
->cb_ctx
, TLS_CERT_CHAIN_FAILURE
, &ev
);
854 wpabuf_free(cert_buf
);
858 #if GNUTLS_VERSION_NUMBER < 0x030300
859 static int server_eku_purpose(gnutls_x509_crt_t cert
)
865 size_t oid_size
= sizeof(oid
);
868 res
= gnutls_x509_crt_get_key_purpose_oid(cert
, i
, oid
,
870 if (res
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
) {
872 /* No EKU - assume any use allowed */
879 wpa_printf(MSG_INFO
, "GnuTLS: Failed to get EKU");
883 wpa_printf(MSG_DEBUG
, "GnuTLS: Certificate purpose: %s", oid
);
884 if (os_strcmp(oid
, GNUTLS_KP_TLS_WWW_SERVER
) == 0 ||
885 os_strcmp(oid
, GNUTLS_KP_ANY
) == 0)
894 static int check_ocsp(struct tls_connection
*conn
, gnutls_session_t session
,
895 gnutls_alert_description_t
*err
)
897 #if GNUTLS_VERSION_NUMBER >= 0x030103
898 gnutls_datum_t response
, buf
;
899 gnutls_ocsp_resp_t resp
;
900 unsigned int cert_status
;
903 if (!(conn
->flags
& (TLS_CONN_REQUEST_OCSP
| TLS_CONN_REQUIRE_OCSP
)))
906 if (!gnutls_ocsp_status_request_is_checked(session
, 0)) {
907 if (conn
->flags
& TLS_CONN_REQUIRE_OCSP
) {
909 "GnuTLS: No valid OCSP response received");
913 wpa_printf(MSG_DEBUG
,
914 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
919 * GnuTLS has already verified the OCSP response in
920 * check_ocsp_response() and rejected handshake if the certificate was
921 * found to be revoked. However, if the response indicates that the
922 * status is unknown, handshake continues and reaches here. We need to
923 * re-import the OCSP response to check for unknown certificate status,
924 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
925 * gnutls_ocsp_resp_verify_direct() calls.
928 res
= gnutls_ocsp_status_request_get(session
, &response
);
929 if (res
!= GNUTLS_E_SUCCESS
) {
931 "GnuTLS: OCSP response was received, but it was not valid");
935 if (gnutls_ocsp_resp_init(&resp
) != GNUTLS_E_SUCCESS
)
938 res
= gnutls_ocsp_resp_import(resp
, &response
);
939 if (res
!= GNUTLS_E_SUCCESS
) {
941 "GnuTLS: Could not parse received OCSP response: %s",
942 gnutls_strerror(res
));
943 gnutls_ocsp_resp_deinit(resp
);
947 res
= gnutls_ocsp_resp_print(resp
, GNUTLS_OCSP_PRINT_FULL
, &buf
);
948 if (res
== GNUTLS_E_SUCCESS
) {
949 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", buf
.data
);
950 gnutls_free(buf
.data
);
953 res
= gnutls_ocsp_resp_get_single(resp
, 0, NULL
, NULL
, NULL
,
954 NULL
, &cert_status
, NULL
,
956 gnutls_ocsp_resp_deinit(resp
);
957 if (res
!= GNUTLS_E_SUCCESS
) {
959 "GnuTLS: Failed to extract OCSP information: %s",
960 gnutls_strerror(res
));
964 if (cert_status
== GNUTLS_OCSP_CERT_GOOD
) {
965 wpa_printf(MSG_DEBUG
, "GnuTLS: OCSP cert status: good");
966 } else if (cert_status
== GNUTLS_OCSP_CERT_REVOKED
) {
967 wpa_printf(MSG_DEBUG
,
968 "GnuTLS: OCSP cert status: revoked");
971 wpa_printf(MSG_DEBUG
,
972 "GnuTLS: OCSP cert status: unknown");
973 if (conn
->flags
& TLS_CONN_REQUIRE_OCSP
)
975 wpa_printf(MSG_DEBUG
,
976 "GnuTLS: OCSP was not required, so allow connection to continue");
982 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
983 "bad certificate status response",
985 *err
= GNUTLS_A_CERTIFICATE_REVOKED
;
987 #else /* GnuTLS 3.1.3 or newer */
989 #endif /* GnuTLS 3.1.3 or newer */
993 static int tls_connection_verify_peer(gnutls_session_t session
)
995 struct tls_connection
*conn
;
996 unsigned int status
, num_certs
, i
;
998 const gnutls_datum_t
*certs
;
999 gnutls_x509_crt_t cert
;
1000 gnutls_alert_description_t err
;
1003 conn
= gnutls_session_get_ptr(session
);
1004 if (!conn
->verify_peer
) {
1005 wpa_printf(MSG_DEBUG
,
1006 "GnuTLS: No peer certificate verification enabled");
1010 wpa_printf(MSG_DEBUG
, "GnuTSL: Verifying peer certificate");
1012 #if GNUTLS_VERSION_NUMBER >= 0x030300
1014 gnutls_typed_vdata_st data
[1];
1015 unsigned int elements
= 0;
1017 os_memset(data
, 0, sizeof(data
));
1018 if (!conn
->global
->server
) {
1019 data
[elements
].type
= GNUTLS_DT_KEY_PURPOSE_OID
;
1020 data
[elements
].data
= (void *) GNUTLS_KP_TLS_WWW_SERVER
;
1023 res
= gnutls_certificate_verify_peers(session
, data
, 1,
1027 res
= gnutls_certificate_verify_peers2(session
, &status
);
1030 wpa_printf(MSG_INFO
, "TLS: Failed to verify peer "
1031 "certificate chain");
1032 err
= GNUTLS_A_INTERNAL_ERROR
;
1036 #if GNUTLS_VERSION_NUMBER >= 0x030104
1038 gnutls_datum_t info
;
1041 type
= gnutls_certificate_type_get(session
);
1042 ret
= gnutls_certificate_verification_status_print(status
, type
,
1045 wpa_printf(MSG_DEBUG
,
1046 "GnuTLS: Failed to print verification status");
1047 err
= GNUTLS_A_INTERNAL_ERROR
;
1050 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", info
.data
);
1051 gnutls_free(info
.data
);
1053 #endif /* GnuTLS 3.1.4 or newer */
1055 certs
= gnutls_certificate_get_peers(session
, &num_certs
);
1056 if (certs
== NULL
|| num_certs
== 0) {
1057 wpa_printf(MSG_INFO
, "TLS: No peer certificate chain received");
1058 err
= GNUTLS_A_UNKNOWN_CA
;
1062 if (conn
->verify_peer
&& (status
& GNUTLS_CERT_INVALID
)) {
1063 wpa_printf(MSG_INFO
, "TLS: Peer certificate not trusted");
1064 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
) {
1065 wpa_printf(MSG_INFO
, "TLS: Certificate uses insecure "
1067 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1068 "certificate uses insecure algorithm",
1069 TLS_FAIL_BAD_CERTIFICATE
);
1070 err
= GNUTLS_A_INSUFFICIENT_SECURITY
;
1073 if (status
& GNUTLS_CERT_NOT_ACTIVATED
) {
1074 wpa_printf(MSG_INFO
, "TLS: Certificate not yet "
1076 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1077 "certificate not yet valid",
1078 TLS_FAIL_NOT_YET_VALID
);
1079 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
1082 if (status
& GNUTLS_CERT_EXPIRED
) {
1083 wpa_printf(MSG_INFO
, "TLS: Certificate expired");
1084 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1085 "certificate has expired",
1087 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
1090 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1091 "untrusted certificate",
1092 TLS_FAIL_UNTRUSTED
);
1093 err
= GNUTLS_A_INTERNAL_ERROR
;
1097 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
) {
1098 wpa_printf(MSG_INFO
, "TLS: Peer certificate does not have a "
1100 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
, "signed not found",
1101 TLS_FAIL_UNTRUSTED
);
1102 err
= GNUTLS_A_UNKNOWN_CA
;
1106 if (status
& GNUTLS_CERT_REVOKED
) {
1107 wpa_printf(MSG_INFO
, "TLS: Peer certificate has been revoked");
1108 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1109 "certificate revoked",
1111 err
= GNUTLS_A_CERTIFICATE_REVOKED
;
1116 wpa_printf(MSG_INFO
, "TLS: Unknown verification status: %d",
1118 err
= GNUTLS_A_INTERNAL_ERROR
;
1122 if (check_ocsp(conn
, session
, &err
))
1127 for (i
= 0; i
< num_certs
; i
++) {
1130 if (gnutls_x509_crt_init(&cert
) < 0) {
1131 wpa_printf(MSG_INFO
, "TLS: Certificate initialization "
1133 err
= GNUTLS_A_BAD_CERTIFICATE
;
1137 if (gnutls_x509_crt_import(cert
, &certs
[i
],
1138 GNUTLS_X509_FMT_DER
) < 0) {
1139 wpa_printf(MSG_INFO
, "TLS: Could not parse peer "
1140 "certificate %d/%d", i
+ 1, num_certs
);
1141 gnutls_x509_crt_deinit(cert
);
1142 err
= GNUTLS_A_BAD_CERTIFICATE
;
1146 gnutls_x509_crt_get_dn(cert
, NULL
, &len
);
1148 buf
= os_malloc(len
+ 1);
1150 buf
[0] = buf
[len
] = '\0';
1151 gnutls_x509_crt_get_dn(cert
, buf
, &len
);
1153 wpa_printf(MSG_DEBUG
, "TLS: Peer cert chain %d/%d: %s",
1154 i
+ 1, num_certs
, buf
);
1156 if (conn
->global
->event_cb
) {
1157 struct wpabuf
*cert_buf
= NULL
;
1158 union tls_event_data ev
;
1159 #ifdef CONFIG_SHA256
1163 #endif /* CONFIG_SHA256 */
1165 os_memset(&ev
, 0, sizeof(ev
));
1166 if (conn
->global
->cert_in_cb
) {
1167 cert_buf
= wpabuf_alloc_copy(certs
[i
].data
,
1169 ev
.peer_cert
.cert
= cert_buf
;
1171 #ifdef CONFIG_SHA256
1172 _addr
[0] = certs
[i
].data
;
1173 _len
[0] = certs
[i
].size
;
1174 if (sha256_vector(1, _addr
, _len
, hash
) == 0) {
1175 ev
.peer_cert
.hash
= hash
;
1176 ev
.peer_cert
.hash_len
= sizeof(hash
);
1178 #endif /* CONFIG_SHA256 */
1179 ev
.peer_cert
.depth
= i
;
1180 ev
.peer_cert
.subject
= buf
;
1181 conn
->global
->event_cb(conn
->global
->cb_ctx
,
1182 TLS_PEER_CERTIFICATE
, &ev
);
1183 wpabuf_free(cert_buf
);
1187 if (conn
->suffix_match
&&
1188 !gnutls_x509_crt_check_hostname(
1189 cert
, conn
->suffix_match
)) {
1190 wpa_printf(MSG_WARNING
,
1191 "TLS: Domain suffix match '%s' not found",
1192 conn
->suffix_match
);
1193 gnutls_tls_fail_event(
1194 conn
, &certs
[i
], i
, buf
,
1195 "Domain suffix mismatch",
1196 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH
);
1197 err
= GNUTLS_A_BAD_CERTIFICATE
;
1198 gnutls_x509_crt_deinit(cert
);
1203 #if GNUTLS_VERSION_NUMBER >= 0x030300
1204 if (conn
->domain_match
&&
1205 !gnutls_x509_crt_check_hostname2(
1206 cert
, conn
->domain_match
,
1207 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS
)) {
1208 wpa_printf(MSG_WARNING
,
1209 "TLS: Domain match '%s' not found",
1210 conn
->domain_match
);
1211 gnutls_tls_fail_event(
1212 conn
, &certs
[i
], i
, buf
,
1214 TLS_FAIL_DOMAIN_MISMATCH
);
1215 err
= GNUTLS_A_BAD_CERTIFICATE
;
1216 gnutls_x509_crt_deinit(cert
);
1220 #endif /* >= 3.3.0 */
1222 /* TODO: validate altsubject_match.
1223 * For now, any such configuration is rejected in
1224 * tls_connection_set_params() */
1226 #if GNUTLS_VERSION_NUMBER < 0x030300
1228 * gnutls_certificate_verify_peers() not available, so
1229 * need to check EKU separately.
1231 if (!conn
->global
->server
&&
1232 !server_eku_purpose(cert
)) {
1233 wpa_printf(MSG_WARNING
,
1234 "GnuTLS: No server EKU");
1235 gnutls_tls_fail_event(
1236 conn
, &certs
[i
], i
, buf
,
1238 TLS_FAIL_BAD_CERTIFICATE
);
1239 err
= GNUTLS_A_BAD_CERTIFICATE
;
1240 gnutls_x509_crt_deinit(cert
);
1244 #endif /* < 3.3.0 */
1247 if (!conn
->disable_time_checks
&&
1248 (gnutls_x509_crt_get_expiration_time(cert
) < now
.sec
||
1249 gnutls_x509_crt_get_activation_time(cert
) > now
.sec
)) {
1250 wpa_printf(MSG_INFO
, "TLS: Peer certificate %d/%d is "
1251 "not valid at this time",
1253 gnutls_tls_fail_event(
1254 conn
, &certs
[i
], i
, buf
,
1255 "Certificate is not valid at this time",
1257 gnutls_x509_crt_deinit(cert
);
1259 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
1265 gnutls_x509_crt_deinit(cert
);
1268 if (conn
->global
->event_cb
!= NULL
)
1269 conn
->global
->event_cb(conn
->global
->cb_ctx
,
1270 TLS_CERT_CHAIN_SUCCESS
, NULL
);
1276 gnutls_alert_send(session
, GNUTLS_AL_FATAL
, err
);
1277 return GNUTLS_E_CERTIFICATE_ERROR
;
1281 static struct wpabuf
* gnutls_get_appl_data(struct tls_connection
*conn
)
1285 wpa_printf(MSG_DEBUG
, "GnuTLS: Check for possible Application Data");
1286 ad
= wpabuf_alloc((wpabuf_len(conn
->pull_buf
) + 500) * 3);
1290 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(ad
),
1292 wpa_printf(MSG_DEBUG
, "GnuTLS: gnutls_record_recv: %d", res
);
1294 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1295 "(%s)", __func__
, (int) res
,
1296 gnutls_strerror(res
));
1301 wpabuf_put(ad
, res
);
1302 wpa_printf(MSG_DEBUG
, "GnuTLS: Received %d bytes of Application Data",
1308 struct wpabuf
* tls_connection_handshake(void *tls_ctx
,
1309 struct tls_connection
*conn
,
1310 const struct wpabuf
*in_data
,
1311 struct wpabuf
**appl_data
)
1313 struct tls_global
*global
= tls_ctx
;
1314 struct wpabuf
*out_data
;
1320 if (in_data
&& wpabuf_len(in_data
) > 0) {
1321 if (conn
->pull_buf
) {
1322 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1323 "pull_buf", __func__
,
1324 (unsigned long) wpabuf_len(conn
->pull_buf
));
1325 wpabuf_free(conn
->pull_buf
);
1327 conn
->pull_buf
= wpabuf_dup(in_data
);
1328 if (conn
->pull_buf
== NULL
)
1330 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1333 ret
= gnutls_handshake(conn
->session
);
1335 gnutls_alert_description_t alert
;
1338 case GNUTLS_E_AGAIN
:
1339 if (global
->server
&& conn
->established
&&
1340 conn
->push_buf
== NULL
) {
1341 /* Need to return something to trigger
1342 * completion of EAP-TLS. */
1343 conn
->push_buf
= wpabuf_alloc(0);
1346 case GNUTLS_E_FATAL_ALERT_RECEIVED
:
1347 alert
= gnutls_alert_get(conn
->session
);
1348 wpa_printf(MSG_DEBUG
, "%s - received fatal '%s' alert",
1349 __func__
, gnutls_alert_get_name(alert
));
1350 conn
->read_alerts
++;
1351 if (conn
->global
->event_cb
!= NULL
) {
1352 union tls_event_data ev
;
1354 os_memset(&ev
, 0, sizeof(ev
));
1355 ev
.alert
.is_local
= 0;
1356 ev
.alert
.type
= gnutls_alert_get_name(alert
);
1357 ev
.alert
.description
= ev
.alert
.type
;
1358 conn
->global
->event_cb(conn
->global
->cb_ctx
,
1363 wpa_printf(MSG_DEBUG
, "%s - gnutls_handshake failed "
1364 "-> %s", __func__
, gnutls_strerror(ret
));
1370 wpa_printf(MSG_DEBUG
, "TLS: Handshake completed successfully");
1372 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1376 desc
= gnutls_session_get_desc(conn
->session
);
1378 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", desc
);
1382 #endif /* GnuTLS 3.1.10 or newer */
1384 conn
->established
= 1;
1385 if (conn
->push_buf
== NULL
) {
1386 /* Need to return something to get final TLS ACK. */
1387 conn
->push_buf
= wpabuf_alloc(0);
1390 gnutls_session_get_data(conn
->session
, NULL
, &size
);
1391 if (global
->session_data
== NULL
||
1392 global
->session_data_size
< size
) {
1393 os_free(global
->session_data
);
1394 global
->session_data
= os_malloc(size
);
1396 if (global
->session_data
) {
1397 global
->session_data_size
= size
;
1398 gnutls_session_get_data(conn
->session
,
1399 global
->session_data
,
1400 &global
->session_data_size
);
1403 if (conn
->pull_buf
&& appl_data
)
1404 *appl_data
= gnutls_get_appl_data(conn
);
1407 out_data
= conn
->push_buf
;
1408 conn
->push_buf
= NULL
;
1413 struct wpabuf
* tls_connection_server_handshake(void *tls_ctx
,
1414 struct tls_connection
*conn
,
1415 const struct wpabuf
*in_data
,
1416 struct wpabuf
**appl_data
)
1418 return tls_connection_handshake(tls_ctx
, conn
, in_data
, appl_data
);
1422 struct wpabuf
* tls_connection_encrypt(void *tls_ctx
,
1423 struct tls_connection
*conn
,
1424 const struct wpabuf
*in_data
)
1429 res
= gnutls_record_send(conn
->session
, wpabuf_head(in_data
),
1430 wpabuf_len(in_data
));
1432 wpa_printf(MSG_INFO
, "%s: Encryption failed: %s",
1433 __func__
, gnutls_strerror(res
));
1437 buf
= conn
->push_buf
;
1438 conn
->push_buf
= NULL
;
1443 struct wpabuf
* tls_connection_decrypt(void *tls_ctx
,
1444 struct tls_connection
*conn
,
1445 const struct wpabuf
*in_data
)
1450 if (conn
->pull_buf
) {
1451 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1452 "pull_buf", __func__
,
1453 (unsigned long) wpabuf_len(conn
->pull_buf
));
1454 wpabuf_free(conn
->pull_buf
);
1456 conn
->pull_buf
= wpabuf_dup(in_data
);
1457 if (conn
->pull_buf
== NULL
)
1459 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1462 * Even though we try to disable TLS compression, it is possible that
1463 * this cannot be done with all TLS libraries. Add extra buffer space
1464 * to handle the possibility of the decrypted data being longer than
1467 out
= wpabuf_alloc((wpabuf_len(in_data
) + 500) * 3);
1471 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(out
),
1474 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1475 "(%s)", __func__
, (int) res
, gnutls_strerror(res
));
1479 wpabuf_put(out
, res
);
1485 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
1489 return gnutls_session_is_resumed(conn
->session
);
1493 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
1501 int tls_get_version(void *ssl_ctx
, struct tls_connection
*conn
,
1502 char *buf
, size_t buflen
)
1504 gnutls_protocol_t ver
;
1506 ver
= gnutls_protocol_get_version(conn
->session
);
1507 if (ver
== GNUTLS_TLS1_0
)
1508 os_strlcpy(buf
, "TLSv1", buflen
);
1509 else if (ver
== GNUTLS_TLS1_1
)
1510 os_strlcpy(buf
, "TLSv1.1", buflen
);
1511 else if (ver
== GNUTLS_TLS1_2
)
1512 os_strlcpy(buf
, "TLSv1.2", buflen
);
1519 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
1520 char *buf
, size_t buflen
)
1528 int tls_connection_enable_workaround(void *ssl_ctx
,
1529 struct tls_connection
*conn
)
1531 gnutls_record_disable_padding(conn
->session
);
1536 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
1537 int ext_type
, const u8
*data
,
1545 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
1549 return conn
->failed
;
1553 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1557 return conn
->read_alerts
;
1561 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1565 return conn
->write_alerts
;
1569 int tls_connection_set_session_ticket_cb(void *tls_ctx
,
1570 struct tls_connection
*conn
,
1571 tls_session_ticket_cb cb
, void *ctx
)
1577 int tls_get_library_version(char *buf
, size_t buf_len
)
1579 return os_snprintf(buf
, buf_len
, "GnuTLS build=%s run=%s",
1580 GNUTLS_VERSION
, gnutls_check_version(NULL
));
1584 void tls_connection_set_success_data(struct tls_connection
*conn
,
1585 struct wpabuf
*data
)
1590 void tls_connection_set_success_data_resumed(struct tls_connection
*conn
)
1595 const struct wpabuf
*
1596 tls_connection_get_success_data(struct tls_connection
*conn
)
1602 void tls_connection_remove_session(struct tls_connection
*conn
)