2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2011, 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>
23 static int tls_gnutls_ref_count
= 0;
26 /* Data for session resumption */
28 size_t session_data_size
;
33 gnutls_certificate_credentials_t xcred
;
35 void (*event_cb
)(void *ctx
, enum tls_event ev
,
36 union tls_event_data
*data
);
41 struct tls_connection
{
42 struct tls_global
*global
;
43 gnutls_session_t session
;
44 int read_alerts
, write_alerts
, failed
;
46 u8
*pre_shared_secret
;
47 size_t pre_shared_secret_len
;
50 unsigned int disable_time_checks
:1;
52 struct wpabuf
*push_buf
;
53 struct wpabuf
*pull_buf
;
54 const u8
*pull_buf_offset
;
57 gnutls_certificate_credentials_t xcred
;
64 static int tls_connection_verify_peer(gnutls_session_t session
);
67 static void tls_log_func(int level
, const char *msg
)
70 if (level
== 6 || level
== 7) {
71 /* These levels seem to be mostly I/O debug and msg dumps */
80 while (*pos
!= '\0') {
87 wpa_printf(level
> 3 ? MSG_MSGDUMP
: MSG_DEBUG
,
88 "gnutls<%d> %s", level
, s
);
93 void * tls_init(const struct tls_config
*conf
)
95 struct tls_global
*global
;
97 if (tls_gnutls_ref_count
== 0) {
99 "GnuTLS: Library version %s (runtime) - %s (build)",
100 gnutls_check_version(NULL
), GNUTLS_VERSION
);
103 global
= os_zalloc(sizeof(*global
));
107 if (tls_gnutls_ref_count
== 0 && gnutls_global_init() < 0) {
111 tls_gnutls_ref_count
++;
113 gnutls_global_set_log_function(tls_log_func
);
114 if (wpa_debug_show_keys
)
115 gnutls_global_set_log_level(11);
118 global
->event_cb
= conf
->event_cb
;
119 global
->cb_ctx
= conf
->cb_ctx
;
120 global
->cert_in_cb
= conf
->cert_in_cb
;
127 void tls_deinit(void *ssl_ctx
)
129 struct tls_global
*global
= ssl_ctx
;
131 if (global
->params_set
)
132 gnutls_certificate_free_credentials(global
->xcred
);
133 os_free(global
->session_data
);
137 tls_gnutls_ref_count
--;
138 if (tls_gnutls_ref_count
== 0)
139 gnutls_global_deinit();
143 int tls_get_errors(void *ssl_ctx
)
149 static ssize_t
tls_pull_func(gnutls_transport_ptr_t ptr
, void *buf
,
152 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
154 if (conn
->pull_buf
== NULL
) {
159 end
= wpabuf_head_u8(conn
->pull_buf
) + wpabuf_len(conn
->pull_buf
);
160 if ((size_t) (end
- conn
->pull_buf_offset
) < len
)
161 len
= end
- conn
->pull_buf_offset
;
162 os_memcpy(buf
, conn
->pull_buf_offset
, len
);
163 conn
->pull_buf_offset
+= len
;
164 if (conn
->pull_buf_offset
== end
) {
165 wpa_printf(MSG_DEBUG
, "%s - pull_buf consumed", __func__
);
166 wpabuf_free(conn
->pull_buf
);
167 conn
->pull_buf
= NULL
;
168 conn
->pull_buf_offset
= NULL
;
170 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in pull_buf",
172 (unsigned long) (end
- conn
->pull_buf_offset
));
178 static ssize_t
tls_push_func(gnutls_transport_ptr_t ptr
, const void *buf
,
181 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
183 if (wpabuf_resize(&conn
->push_buf
, len
) < 0) {
187 wpabuf_put_data(conn
->push_buf
, buf
, len
);
193 static int tls_gnutls_init_session(struct tls_global
*global
,
194 struct tls_connection
*conn
)
199 ret
= gnutls_init(&conn
->session
,
200 global
->server
? GNUTLS_SERVER
: GNUTLS_CLIENT
);
202 wpa_printf(MSG_INFO
, "TLS: Failed to initialize new TLS "
203 "connection: %s", gnutls_strerror(ret
));
207 ret
= gnutls_set_default_priority(conn
->session
);
211 ret
= gnutls_priority_set_direct(conn
->session
, "NORMAL:-VERS-SSL3.0",
214 wpa_printf(MSG_ERROR
, "GnuTLS: Priority string failure at "
219 gnutls_transport_set_pull_function(conn
->session
, tls_pull_func
);
220 gnutls_transport_set_push_function(conn
->session
, tls_push_func
);
221 gnutls_transport_set_ptr(conn
->session
, (gnutls_transport_ptr_t
) conn
);
222 gnutls_session_set_ptr(conn
->session
, conn
);
227 wpa_printf(MSG_INFO
, "TLS: Failed to setup new TLS connection: %s",
228 gnutls_strerror(ret
));
229 gnutls_deinit(conn
->session
);
234 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
236 struct tls_global
*global
= ssl_ctx
;
237 struct tls_connection
*conn
;
240 conn
= os_zalloc(sizeof(*conn
));
243 conn
->global
= global
;
245 if (tls_gnutls_init_session(global
, conn
)) {
250 if (global
->params_set
) {
251 ret
= gnutls_credentials_set(conn
->session
,
252 GNUTLS_CRD_CERTIFICATE
,
255 wpa_printf(MSG_INFO
, "Failed to configure "
256 "credentials: %s", gnutls_strerror(ret
));
262 if (gnutls_certificate_allocate_credentials(&conn
->xcred
)) {
271 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*conn
)
276 gnutls_certificate_free_credentials(conn
->xcred
);
277 gnutls_deinit(conn
->session
);
278 os_free(conn
->pre_shared_secret
);
279 wpabuf_free(conn
->push_buf
);
280 wpabuf_free(conn
->pull_buf
);
281 os_free(conn
->suffix_match
);
286 int tls_connection_established(void *ssl_ctx
, struct tls_connection
*conn
)
288 return conn
? conn
->established
: 0;
292 int tls_connection_shutdown(void *ssl_ctx
, struct tls_connection
*conn
)
294 struct tls_global
*global
= ssl_ctx
;
300 /* Shutdown previous TLS connection without notifying the peer
301 * because the connection was already terminated in practice
302 * and "close notify" shutdown alert would confuse AS. */
303 gnutls_bye(conn
->session
, GNUTLS_SHUT_RDWR
);
304 wpabuf_free(conn
->push_buf
);
305 conn
->push_buf
= NULL
;
306 conn
->established
= 0;
308 gnutls_deinit(conn
->session
);
309 if (tls_gnutls_init_session(global
, conn
)) {
310 wpa_printf(MSG_INFO
, "GnuTLS: Failed to preparare new session "
311 "for session resumption use");
315 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
316 conn
->params_set
? conn
->xcred
:
319 wpa_printf(MSG_INFO
, "GnuTLS: Failed to configure credentials "
320 "for session resumption: %s", gnutls_strerror(ret
));
324 if (global
->session_data
) {
325 ret
= gnutls_session_set_data(conn
->session
,
326 global
->session_data
,
327 global
->session_data_size
);
329 wpa_printf(MSG_INFO
, "GnuTLS: Failed to set session "
330 "data: %s", gnutls_strerror(ret
));
339 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
340 const struct tls_connection_params
*params
)
344 if (conn
== NULL
|| params
== NULL
)
347 if (params
->subject_match
) {
348 wpa_printf(MSG_INFO
, "GnuTLS: subject_match not supported");
352 if (params
->altsubject_match
) {
353 wpa_printf(MSG_INFO
, "GnuTLS: altsubject_match not supported");
357 os_free(conn
->suffix_match
);
358 conn
->suffix_match
= NULL
;
359 if (params
->suffix_match
) {
360 conn
->suffix_match
= os_strdup(params
->suffix_match
);
361 if (conn
->suffix_match
== NULL
)
365 conn
->flags
= params
->flags
;
367 if (params
->openssl_ciphers
) {
368 wpa_printf(MSG_INFO
, "GnuTLS: openssl_ciphers not supported");
372 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
373 * to force peer validation(?) */
375 if (params
->ca_cert
) {
376 wpa_printf(MSG_DEBUG
, "GnuTLS: Try to parse %s in DER format",
378 ret
= gnutls_certificate_set_x509_trust_file(
379 conn
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_DER
);
381 wpa_printf(MSG_DEBUG
,
382 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
384 gnutls_strerror(ret
));
385 ret
= gnutls_certificate_set_x509_trust_file(
386 conn
->xcred
, params
->ca_cert
,
387 GNUTLS_X509_FMT_PEM
);
389 wpa_printf(MSG_DEBUG
,
390 "Failed to read CA cert '%s' in PEM format: %s",
392 gnutls_strerror(ret
));
396 } else if (params
->ca_cert_blob
) {
399 ca
.data
= (unsigned char *) params
->ca_cert_blob
;
400 ca
.size
= params
->ca_cert_blob_len
;
402 ret
= gnutls_certificate_set_x509_trust_mem(
403 conn
->xcred
, &ca
, GNUTLS_X509_FMT_DER
);
405 wpa_printf(MSG_DEBUG
,
406 "Failed to parse CA cert in DER format: %s",
407 gnutls_strerror(ret
));
408 ret
= gnutls_certificate_set_x509_trust_mem(
409 conn
->xcred
, &ca
, GNUTLS_X509_FMT_PEM
);
411 wpa_printf(MSG_DEBUG
,
412 "Failed to parse CA cert in PEM format: %s",
413 gnutls_strerror(ret
));
417 } else if (params
->ca_path
) {
418 wpa_printf(MSG_INFO
, "GnuTLS: ca_path not supported");
422 conn
->disable_time_checks
= 0;
423 if (params
->ca_cert
|| params
->ca_cert_blob
) {
424 conn
->verify_peer
= 1;
425 gnutls_certificate_set_verify_function(
426 conn
->xcred
, tls_connection_verify_peer
);
428 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
429 gnutls_certificate_set_verify_flags(
430 conn
->xcred
, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
433 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
434 conn
->disable_time_checks
= 1;
435 gnutls_certificate_set_verify_flags(
437 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
441 if (params
->client_cert
&& params
->private_key
) {
442 #if GNUTLS_VERSION_NUMBER >= 0x03010b
443 ret
= gnutls_certificate_set_x509_key_file2(
444 conn
->xcred
, params
->client_cert
, params
->private_key
,
445 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
, 0);
447 /* private_key_passwd not (easily) supported here */
448 ret
= gnutls_certificate_set_x509_key_file(
449 conn
->xcred
, params
->client_cert
, params
->private_key
,
450 GNUTLS_X509_FMT_DER
);
453 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
454 "in DER format: %s", gnutls_strerror(ret
));
455 #if GNUTLS_VERSION_NUMBER >= 0x03010b
456 ret
= gnutls_certificate_set_x509_key_file2(
457 conn
->xcred
, params
->client_cert
,
458 params
->private_key
, GNUTLS_X509_FMT_PEM
,
459 params
->private_key_passwd
, 0);
461 ret
= gnutls_certificate_set_x509_key_file(
462 conn
->xcred
, params
->client_cert
,
463 params
->private_key
, GNUTLS_X509_FMT_PEM
);
466 wpa_printf(MSG_DEBUG
, "Failed to read client "
467 "cert/key in PEM format: %s",
468 gnutls_strerror(ret
));
472 } else if (params
->private_key
) {
475 /* Try to load in PKCS#12 format */
476 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
477 conn
->xcred
, params
->private_key
, GNUTLS_X509_FMT_DER
,
478 params
->private_key_passwd
);
480 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
481 "PKCS#12 format: %s", gnutls_strerror(ret
));
485 #endif /* PKCS12_FUNCS */
488 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
492 } else if (params
->client_cert_blob
&& params
->private_key_blob
) {
493 gnutls_datum_t cert
, key
;
495 cert
.data
= (unsigned char *) params
->client_cert_blob
;
496 cert
.size
= params
->client_cert_blob_len
;
497 key
.data
= (unsigned char *) params
->private_key_blob
;
498 key
.size
= params
->private_key_blob_len
;
500 #if GNUTLS_VERSION_NUMBER >= 0x03010b
501 ret
= gnutls_certificate_set_x509_key_mem2(
502 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_DER
,
503 params
->private_key_passwd
, 0);
505 /* private_key_passwd not (easily) supported here */
506 ret
= gnutls_certificate_set_x509_key_mem(
507 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_DER
);
510 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
511 "in DER format: %s", gnutls_strerror(ret
));
512 #if GNUTLS_VERSION_NUMBER >= 0x03010b
513 ret
= gnutls_certificate_set_x509_key_mem2(
514 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_PEM
,
515 params
->private_key_passwd
, 0);
517 /* private_key_passwd not (easily) supported here */
518 ret
= gnutls_certificate_set_x509_key_mem(
519 conn
->xcred
, &cert
, &key
, GNUTLS_X509_FMT_PEM
);
522 wpa_printf(MSG_DEBUG
, "Failed to read client "
523 "cert/key in PEM format: %s",
524 gnutls_strerror(ret
));
528 } else if (params
->private_key_blob
) {
532 key
.data
= (unsigned char *) params
->private_key_blob
;
533 key
.size
= params
->private_key_blob_len
;
535 /* Try to load in PKCS#12 format */
536 ret
= gnutls_certificate_set_x509_simple_pkcs12_mem(
537 conn
->xcred
, &key
, GNUTLS_X509_FMT_DER
,
538 params
->private_key_passwd
);
540 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
541 "PKCS#12 format: %s", gnutls_strerror(ret
));
544 #else /* PKCS12_FUNCS */
545 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not included");
547 #endif /* PKCS12_FUNCS */
550 #if GNUTLS_VERSION_NUMBER >= 0x030103
551 if (params
->flags
& (TLS_CONN_REQUEST_OCSP
| TLS_CONN_REQUIRE_OCSP
)) {
552 ret
= gnutls_ocsp_status_request_enable_client(conn
->session
,
554 if (ret
!= GNUTLS_E_SUCCESS
) {
556 "GnuTLS: Failed to enable OCSP client");
561 if (params
->flags
& TLS_CONN_REQUIRE_OCSP
) {
563 "GnuTLS: OCSP not supported by this version of GnuTLS");
568 conn
->params_set
= 1;
570 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
573 wpa_printf(MSG_INFO
, "Failed to configure credentials: %s",
574 gnutls_strerror(ret
));
581 int tls_global_set_params(void *tls_ctx
,
582 const struct tls_connection_params
*params
)
584 struct tls_global
*global
= tls_ctx
;
587 /* Currently, global parameters are only set when running in server
591 if (global
->params_set
) {
592 gnutls_certificate_free_credentials(global
->xcred
);
593 global
->params_set
= 0;
596 ret
= gnutls_certificate_allocate_credentials(&global
->xcred
);
598 wpa_printf(MSG_DEBUG
, "Failed to allocate global credentials "
599 "%s", gnutls_strerror(ret
));
603 if (params
->ca_cert
) {
604 ret
= gnutls_certificate_set_x509_trust_file(
605 global
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_DER
);
607 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
608 "in DER format: %s", params
->ca_cert
,
609 gnutls_strerror(ret
));
610 ret
= gnutls_certificate_set_x509_trust_file(
611 global
->xcred
, params
->ca_cert
,
612 GNUTLS_X509_FMT_PEM
);
614 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
615 "'%s' in PEM format: %s",
617 gnutls_strerror(ret
));
622 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
623 gnutls_certificate_set_verify_flags(
625 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
628 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
629 gnutls_certificate_set_verify_flags(
631 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
635 if (params
->client_cert
&& params
->private_key
) {
636 /* TODO: private_key_passwd? */
637 ret
= gnutls_certificate_set_x509_key_file(
638 global
->xcred
, params
->client_cert
,
639 params
->private_key
, GNUTLS_X509_FMT_DER
);
641 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
642 "in DER format: %s", gnutls_strerror(ret
));
643 ret
= gnutls_certificate_set_x509_key_file(
644 global
->xcred
, params
->client_cert
,
645 params
->private_key
, GNUTLS_X509_FMT_PEM
);
647 wpa_printf(MSG_DEBUG
, "Failed to read client "
648 "cert/key in PEM format: %s",
649 gnutls_strerror(ret
));
653 } else if (params
->private_key
) {
656 /* Try to load in PKCS#12 format */
657 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
658 global
->xcred
, params
->private_key
,
659 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
);
661 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
662 "PKCS#12 format: %s", gnutls_strerror(ret
));
666 #endif /* PKCS12_FUNCS */
669 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
675 global
->params_set
= 1;
680 gnutls_certificate_free_credentials(global
->xcred
);
685 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
692 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
695 if (conn
== NULL
|| conn
->session
== NULL
)
698 conn
->verify_peer
= verify_peer
;
699 gnutls_certificate_server_set_request(conn
->session
,
700 verify_peer
? GNUTLS_CERT_REQUIRE
701 : GNUTLS_CERT_REQUEST
);
707 int tls_connection_get_keys(void *ssl_ctx
, struct tls_connection
*conn
,
708 struct tls_keys
*keys
)
710 #if GNUTLS_VERSION_NUMBER >= 0x030012
711 gnutls_datum_t client
, server
;
713 if (conn
== NULL
|| conn
->session
== NULL
|| keys
== NULL
)
716 os_memset(keys
, 0, sizeof(*keys
));
717 gnutls_session_get_random(conn
->session
, &client
, &server
);
718 keys
->client_random
= client
.data
;
719 keys
->server_random
= server
.data
;
720 keys
->client_random_len
= client
.size
;
721 keys
->server_random_len
= client
.size
;
730 int tls_connection_prf(void *tls_ctx
, struct tls_connection
*conn
,
731 const char *label
, int server_random_first
,
732 u8
*out
, size_t out_len
)
734 if (conn
== NULL
|| conn
->session
== NULL
)
737 return gnutls_prf(conn
->session
, os_strlen(label
), label
,
738 server_random_first
, 0, NULL
, out_len
, (char *) out
);
742 static void gnutls_tls_fail_event(struct tls_connection
*conn
,
743 const gnutls_datum_t
*cert
, int depth
,
744 const char *subject
, const char *err_str
,
745 enum tls_fail_reason reason
)
747 union tls_event_data ev
;
748 struct tls_global
*global
= conn
->global
;
749 struct wpabuf
*cert_buf
= NULL
;
751 if (global
->event_cb
== NULL
)
754 os_memset(&ev
, 0, sizeof(ev
));
755 ev
.cert_fail
.depth
= depth
;
756 ev
.cert_fail
.subject
= subject
? subject
: "";
757 ev
.cert_fail
.reason
= reason
;
758 ev
.cert_fail
.reason_txt
= err_str
;
760 cert_buf
= wpabuf_alloc_copy(cert
->data
, cert
->size
);
761 ev
.cert_fail
.cert
= cert_buf
;
763 global
->event_cb(global
->cb_ctx
, TLS_CERT_CHAIN_FAILURE
, &ev
);
764 wpabuf_free(cert_buf
);
768 #if GNUTLS_VERSION_NUMBER < 0x030300
769 static int server_eku_purpose(gnutls_x509_crt_t cert
)
775 size_t oid_size
= sizeof(oid
);
778 res
= gnutls_x509_crt_get_key_purpose_oid(cert
, i
, oid
,
780 if (res
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
) {
782 /* No EKU - assume any use allowed */
789 wpa_printf(MSG_INFO
, "GnuTLS: Failed to get EKU");
793 wpa_printf(MSG_DEBUG
, "GnuTLS: Certificate purpose: %s", oid
);
794 if (os_strcmp(oid
, GNUTLS_KP_TLS_WWW_SERVER
) == 0 ||
795 os_strcmp(oid
, GNUTLS_KP_ANY
) == 0)
804 static int check_ocsp(struct tls_connection
*conn
, gnutls_session_t session
,
805 gnutls_alert_description_t
*err
)
807 #if GNUTLS_VERSION_NUMBER >= 0x030103
808 gnutls_datum_t response
, buf
;
809 gnutls_ocsp_resp_t resp
;
810 unsigned int cert_status
;
813 if (!(conn
->flags
& (TLS_CONN_REQUEST_OCSP
| TLS_CONN_REQUIRE_OCSP
)))
816 if (!gnutls_ocsp_status_request_is_checked(session
, 0)) {
817 if (conn
->flags
& TLS_CONN_REQUIRE_OCSP
) {
819 "GnuTLS: No valid OCSP response received");
823 wpa_printf(MSG_DEBUG
,
824 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
829 * GnuTLS has already verified the OCSP response in
830 * check_ocsp_response() and rejected handshake if the certificate was
831 * found to be revoked. However, if the response indicates that the
832 * status is unknown, handshake continues and reaches here. We need to
833 * re-import the OCSP response to check for unknown certificate status,
834 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
835 * gnutls_ocsp_resp_verify_direct() calls.
838 res
= gnutls_ocsp_status_request_get(session
, &response
);
839 if (res
!= GNUTLS_E_SUCCESS
) {
841 "GnuTLS: OCSP response was received, but it was not valid");
845 if (gnutls_ocsp_resp_init(&resp
) != GNUTLS_E_SUCCESS
)
848 res
= gnutls_ocsp_resp_import(resp
, &response
);
849 if (res
!= GNUTLS_E_SUCCESS
) {
851 "GnuTLS: Could not parse received OCSP response: %s",
852 gnutls_strerror(res
));
853 gnutls_ocsp_resp_deinit(resp
);
857 res
= gnutls_ocsp_resp_print(resp
, GNUTLS_OCSP_PRINT_FULL
, &buf
);
858 if (res
== GNUTLS_E_SUCCESS
) {
859 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", buf
.data
);
860 gnutls_free(buf
.data
);
863 res
= gnutls_ocsp_resp_get_single(resp
, 0, NULL
, NULL
, NULL
,
864 NULL
, &cert_status
, NULL
,
866 gnutls_ocsp_resp_deinit(resp
);
867 if (res
!= GNUTLS_E_SUCCESS
) {
869 "GnuTLS: Failed to extract OCSP information: %s",
870 gnutls_strerror(res
));
874 if (cert_status
== GNUTLS_OCSP_CERT_GOOD
) {
875 wpa_printf(MSG_DEBUG
, "GnuTLS: OCSP cert status: good");
876 } else if (cert_status
== GNUTLS_OCSP_CERT_REVOKED
) {
877 wpa_printf(MSG_DEBUG
,
878 "GnuTLS: OCSP cert status: revoked");
881 wpa_printf(MSG_DEBUG
,
882 "GnuTLS: OCSP cert status: unknown");
883 if (conn
->flags
& TLS_CONN_REQUIRE_OCSP
)
885 wpa_printf(MSG_DEBUG
,
886 "GnuTLS: OCSP was not required, so allow connection to continue");
892 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
893 "bad certificate status response",
895 *err
= GNUTLS_A_CERTIFICATE_REVOKED
;
897 #else /* GnuTLS 3.1.3 or newer */
899 #endif /* GnuTLS 3.1.3 or newer */
903 static int tls_connection_verify_peer(gnutls_session_t session
)
905 struct tls_connection
*conn
;
906 unsigned int status
, num_certs
, i
;
908 const gnutls_datum_t
*certs
;
909 gnutls_x509_crt_t cert
;
910 gnutls_alert_description_t err
;
913 conn
= gnutls_session_get_ptr(session
);
914 if (!conn
->verify_peer
) {
915 wpa_printf(MSG_DEBUG
,
916 "GnuTLS: No peer certificate verification enabled");
920 wpa_printf(MSG_DEBUG
, "GnuTSL: Verifying peer certificate");
922 #if GNUTLS_VERSION_NUMBER >= 0x030300
924 gnutls_typed_vdata_st data
[1];
925 unsigned int elements
= 0;
927 os_memset(data
, 0, sizeof(data
));
928 if (!conn
->global
->server
) {
929 data
[elements
].type
= GNUTLS_DT_KEY_PURPOSE_OID
;
930 data
[elements
].data
= (void *) GNUTLS_KP_TLS_WWW_SERVER
;
933 res
= gnutls_certificate_verify_peers(session
, data
, 1,
937 res
= gnutls_certificate_verify_peers2(session
, &status
);
940 wpa_printf(MSG_INFO
, "TLS: Failed to verify peer "
941 "certificate chain");
942 err
= GNUTLS_A_INTERNAL_ERROR
;
946 #if GNUTLS_VERSION_NUMBER >= 0x030104
951 type
= gnutls_certificate_type_get(session
);
952 ret
= gnutls_certificate_verification_status_print(status
, type
,
955 wpa_printf(MSG_DEBUG
,
956 "GnuTLS: Failed to print verification status");
957 err
= GNUTLS_A_INTERNAL_ERROR
;
960 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", info
.data
);
961 gnutls_free(info
.data
);
963 #endif /* GnuTLS 3.1.4 or newer */
965 certs
= gnutls_certificate_get_peers(session
, &num_certs
);
966 if (certs
== NULL
|| num_certs
== 0) {
967 wpa_printf(MSG_INFO
, "TLS: No peer certificate chain received");
968 err
= GNUTLS_A_UNKNOWN_CA
;
972 if (conn
->verify_peer
&& (status
& GNUTLS_CERT_INVALID
)) {
973 wpa_printf(MSG_INFO
, "TLS: Peer certificate not trusted");
974 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
) {
975 wpa_printf(MSG_INFO
, "TLS: Certificate uses insecure "
977 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
978 "certificate uses insecure algorithm",
979 TLS_FAIL_BAD_CERTIFICATE
);
980 err
= GNUTLS_A_INSUFFICIENT_SECURITY
;
983 if (status
& GNUTLS_CERT_NOT_ACTIVATED
) {
984 wpa_printf(MSG_INFO
, "TLS: Certificate not yet "
986 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
987 "certificate not yet valid",
988 TLS_FAIL_NOT_YET_VALID
);
989 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
992 if (status
& GNUTLS_CERT_EXPIRED
) {
993 wpa_printf(MSG_INFO
, "TLS: Certificate expired");
994 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
995 "certificate has expired",
997 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
1000 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1001 "untrusted certificate",
1002 TLS_FAIL_UNTRUSTED
);
1003 err
= GNUTLS_A_INTERNAL_ERROR
;
1007 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
) {
1008 wpa_printf(MSG_INFO
, "TLS: Peer certificate does not have a "
1010 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
, "signed not found",
1011 TLS_FAIL_UNTRUSTED
);
1012 err
= GNUTLS_A_UNKNOWN_CA
;
1016 if (status
& GNUTLS_CERT_REVOKED
) {
1017 wpa_printf(MSG_INFO
, "TLS: Peer certificate has been revoked");
1018 gnutls_tls_fail_event(conn
, NULL
, 0, NULL
,
1019 "certificate revoked",
1021 err
= GNUTLS_A_CERTIFICATE_REVOKED
;
1026 wpa_printf(MSG_INFO
, "TLS: Unknown verification status: %d",
1028 err
= GNUTLS_A_INTERNAL_ERROR
;
1032 if (check_ocsp(conn
, session
, &err
))
1037 for (i
= 0; i
< num_certs
; i
++) {
1040 if (gnutls_x509_crt_init(&cert
) < 0) {
1041 wpa_printf(MSG_INFO
, "TLS: Certificate initialization "
1043 err
= GNUTLS_A_BAD_CERTIFICATE
;
1047 if (gnutls_x509_crt_import(cert
, &certs
[i
],
1048 GNUTLS_X509_FMT_DER
) < 0) {
1049 wpa_printf(MSG_INFO
, "TLS: Could not parse peer "
1050 "certificate %d/%d", i
+ 1, num_certs
);
1051 gnutls_x509_crt_deinit(cert
);
1052 err
= GNUTLS_A_BAD_CERTIFICATE
;
1056 gnutls_x509_crt_get_dn(cert
, NULL
, &len
);
1058 buf
= os_malloc(len
+ 1);
1060 buf
[0] = buf
[len
] = '\0';
1061 gnutls_x509_crt_get_dn(cert
, buf
, &len
);
1063 wpa_printf(MSG_DEBUG
, "TLS: Peer cert chain %d/%d: %s",
1064 i
+ 1, num_certs
, buf
);
1067 if (conn
->suffix_match
&&
1068 !gnutls_x509_crt_check_hostname(
1069 cert
, conn
->suffix_match
)) {
1070 wpa_printf(MSG_WARNING
,
1071 "TLS: Domain suffix match '%s' not found",
1072 conn
->suffix_match
);
1073 gnutls_tls_fail_event(
1074 conn
, &certs
[i
], i
, buf
,
1075 "Domain suffix mismatch",
1076 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH
);
1077 err
= GNUTLS_A_BAD_CERTIFICATE
;
1078 gnutls_x509_crt_deinit(cert
);
1083 /* TODO: validate altsubject_match.
1084 * For now, any such configuration is rejected in
1085 * tls_connection_set_params() */
1087 #if GNUTLS_VERSION_NUMBER < 0x030300
1089 * gnutls_certificate_verify_peers() not available, so
1090 * need to check EKU separately.
1092 if (!conn
->global
->server
&&
1093 !server_eku_purpose(cert
)) {
1094 wpa_printf(MSG_WARNING
,
1095 "GnuTLS: No server EKU");
1096 gnutls_tls_fail_event(
1097 conn
, &certs
[i
], i
, buf
,
1099 TLS_FAIL_BAD_CERTIFICATE
);
1100 err
= GNUTLS_A_BAD_CERTIFICATE
;
1101 gnutls_x509_crt_deinit(cert
);
1105 #endif /* < 3.3.0 */
1108 if (!conn
->disable_time_checks
&&
1109 (gnutls_x509_crt_get_expiration_time(cert
) < now
.sec
||
1110 gnutls_x509_crt_get_activation_time(cert
) > now
.sec
)) {
1111 wpa_printf(MSG_INFO
, "TLS: Peer certificate %d/%d is "
1112 "not valid at this time",
1114 gnutls_tls_fail_event(
1115 conn
, &certs
[i
], i
, buf
,
1116 "Certificate is not valid at this time",
1118 gnutls_x509_crt_deinit(cert
);
1120 err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
1126 gnutls_x509_crt_deinit(cert
);
1133 gnutls_alert_send(session
, GNUTLS_AL_FATAL
, err
);
1134 return GNUTLS_E_CERTIFICATE_ERROR
;
1138 static struct wpabuf
* gnutls_get_appl_data(struct tls_connection
*conn
)
1142 wpa_printf(MSG_DEBUG
, "GnuTLS: Check for possible Application Data");
1143 ad
= wpabuf_alloc((wpabuf_len(conn
->pull_buf
) + 500) * 3);
1147 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(ad
),
1149 wpa_printf(MSG_DEBUG
, "GnuTLS: gnutls_record_recv: %d", res
);
1151 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1152 "(%s)", __func__
, (int) res
,
1153 gnutls_strerror(res
));
1158 wpabuf_put(ad
, res
);
1159 wpa_printf(MSG_DEBUG
, "GnuTLS: Received %d bytes of Application Data",
1165 struct wpabuf
* tls_connection_handshake(void *tls_ctx
,
1166 struct tls_connection
*conn
,
1167 const struct wpabuf
*in_data
,
1168 struct wpabuf
**appl_data
)
1170 struct tls_global
*global
= tls_ctx
;
1171 struct wpabuf
*out_data
;
1177 if (in_data
&& wpabuf_len(in_data
) > 0) {
1178 if (conn
->pull_buf
) {
1179 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1180 "pull_buf", __func__
,
1181 (unsigned long) wpabuf_len(conn
->pull_buf
));
1182 wpabuf_free(conn
->pull_buf
);
1184 conn
->pull_buf
= wpabuf_dup(in_data
);
1185 if (conn
->pull_buf
== NULL
)
1187 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1190 ret
= gnutls_handshake(conn
->session
);
1193 case GNUTLS_E_AGAIN
:
1194 if (global
->server
&& conn
->established
&&
1195 conn
->push_buf
== NULL
) {
1196 /* Need to return something to trigger
1197 * completion of EAP-TLS. */
1198 conn
->push_buf
= wpabuf_alloc(0);
1201 case GNUTLS_E_FATAL_ALERT_RECEIVED
:
1202 wpa_printf(MSG_DEBUG
, "%s - received fatal '%s' alert",
1203 __func__
, gnutls_alert_get_name(
1204 gnutls_alert_get(conn
->session
)));
1205 conn
->read_alerts
++;
1208 wpa_printf(MSG_DEBUG
, "%s - gnutls_handshake failed "
1209 "-> %s", __func__
, gnutls_strerror(ret
));
1215 wpa_printf(MSG_DEBUG
, "TLS: Handshake completed successfully");
1217 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1221 desc
= gnutls_session_get_desc(conn
->session
);
1223 wpa_printf(MSG_DEBUG
, "GnuTLS: %s", desc
);
1227 #endif /* GnuTLS 3.1.10 or newer */
1229 conn
->established
= 1;
1230 if (conn
->push_buf
== NULL
) {
1231 /* Need to return something to get final TLS ACK. */
1232 conn
->push_buf
= wpabuf_alloc(0);
1235 gnutls_session_get_data(conn
->session
, NULL
, &size
);
1236 if (global
->session_data
== NULL
||
1237 global
->session_data_size
< size
) {
1238 os_free(global
->session_data
);
1239 global
->session_data
= os_malloc(size
);
1241 if (global
->session_data
) {
1242 global
->session_data_size
= size
;
1243 gnutls_session_get_data(conn
->session
,
1244 global
->session_data
,
1245 &global
->session_data_size
);
1248 if (conn
->pull_buf
&& appl_data
)
1249 *appl_data
= gnutls_get_appl_data(conn
);
1252 out_data
= conn
->push_buf
;
1253 conn
->push_buf
= NULL
;
1258 struct wpabuf
* tls_connection_server_handshake(void *tls_ctx
,
1259 struct tls_connection
*conn
,
1260 const struct wpabuf
*in_data
,
1261 struct wpabuf
**appl_data
)
1263 return tls_connection_handshake(tls_ctx
, conn
, in_data
, appl_data
);
1267 struct wpabuf
* tls_connection_encrypt(void *tls_ctx
,
1268 struct tls_connection
*conn
,
1269 const struct wpabuf
*in_data
)
1274 res
= gnutls_record_send(conn
->session
, wpabuf_head(in_data
),
1275 wpabuf_len(in_data
));
1277 wpa_printf(MSG_INFO
, "%s: Encryption failed: %s",
1278 __func__
, gnutls_strerror(res
));
1282 buf
= conn
->push_buf
;
1283 conn
->push_buf
= NULL
;
1288 struct wpabuf
* tls_connection_decrypt(void *tls_ctx
,
1289 struct tls_connection
*conn
,
1290 const struct wpabuf
*in_data
)
1295 if (conn
->pull_buf
) {
1296 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1297 "pull_buf", __func__
,
1298 (unsigned long) wpabuf_len(conn
->pull_buf
));
1299 wpabuf_free(conn
->pull_buf
);
1301 conn
->pull_buf
= wpabuf_dup(in_data
);
1302 if (conn
->pull_buf
== NULL
)
1304 conn
->pull_buf_offset
= wpabuf_head(conn
->pull_buf
);
1307 * Even though we try to disable TLS compression, it is possible that
1308 * this cannot be done with all TLS libraries. Add extra buffer space
1309 * to handle the possibility of the decrypted data being longer than
1312 out
= wpabuf_alloc((wpabuf_len(in_data
) + 500) * 3);
1316 res
= gnutls_record_recv(conn
->session
, wpabuf_mhead(out
),
1319 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1320 "(%s)", __func__
, (int) res
, gnutls_strerror(res
));
1324 wpabuf_put(out
, res
);
1330 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
1334 return gnutls_session_is_resumed(conn
->session
);
1338 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
1346 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
1347 char *buf
, size_t buflen
)
1355 int tls_connection_enable_workaround(void *ssl_ctx
,
1356 struct tls_connection
*conn
)
1358 gnutls_record_disable_padding(conn
->session
);
1363 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
1364 int ext_type
, const u8
*data
,
1372 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
1376 return conn
->failed
;
1380 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1384 return conn
->read_alerts
;
1388 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1392 return conn
->write_alerts
;
1396 int tls_connection_get_keyblock_size(void *tls_ctx
,
1397 struct tls_connection
*conn
)
1404 unsigned int tls_capabilities(void *tls_ctx
)
1410 int tls_connection_set_session_ticket_cb(void *tls_ctx
,
1411 struct tls_connection
*conn
,
1412 tls_session_ticket_cb cb
, void *ctx
)
1418 int tls_get_library_version(char *buf
, size_t buf_len
)
1420 return os_snprintf(buf
, buf_len
, "GnuTLS build=%s run=%s",
1421 GNUTLS_VERSION
, gnutls_check_version(NULL
));