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>
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);
42 struct tls_connection {
43 struct tls_global *global;
44 gnutls_session_t session;
45 int read_alerts, write_alerts, failed;
47 u8 *pre_shared_secret;
48 size_t pre_shared_secret_len;
51 unsigned int disable_time_checks:1;
53 struct wpabuf *push_buf;
54 struct wpabuf *pull_buf;
55 const u8 *pull_buf_offset;
58 gnutls_certificate_credentials_t xcred;
66 static int tls_connection_verify_peer(gnutls_session_t session);
69 static void tls_log_func(int level, const char *msg)
72 if (level == 6 || level == 7) {
73 /* These levels seem to be mostly I/O debug and msg dumps */
82 while (*pos != '\0') {
89 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
90 "gnutls<%d> %s", level, s);
95 void * tls_init(const struct tls_config *conf)
97 struct tls_global *global;
99 if (tls_gnutls_ref_count == 0) {
100 wpa_printf(MSG_DEBUG,
101 "GnuTLS: Library version %s (runtime) - %s (build)",
102 gnutls_check_version(NULL), GNUTLS_VERSION);
105 global = os_zalloc(sizeof(*global));
109 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
113 tls_gnutls_ref_count++;
115 gnutls_global_set_log_function(tls_log_func);
116 if (wpa_debug_show_keys)
117 gnutls_global_set_log_level(11);
120 global->event_cb = conf->event_cb;
121 global->cb_ctx = conf->cb_ctx;
122 global->cert_in_cb = conf->cert_in_cb;
129 void tls_deinit(void *ssl_ctx)
131 struct tls_global *global = ssl_ctx;
133 if (global->params_set)
134 gnutls_certificate_free_credentials(global->xcred);
135 os_free(global->session_data);
139 tls_gnutls_ref_count--;
140 if (tls_gnutls_ref_count == 0)
141 gnutls_global_deinit();
145 int tls_get_errors(void *ssl_ctx)
151 static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
154 struct tls_connection *conn = (struct tls_connection *) ptr;
156 if (conn->pull_buf == NULL) {
161 end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
162 if ((size_t) (end - conn->pull_buf_offset) < len)
163 len = end - conn->pull_buf_offset;
164 os_memcpy(buf, conn->pull_buf_offset, len);
165 conn->pull_buf_offset += len;
166 if (conn->pull_buf_offset == end) {
167 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
168 wpabuf_free(conn->pull_buf);
169 conn->pull_buf = NULL;
170 conn->pull_buf_offset = NULL;
172 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
174 (unsigned long) (end - conn->pull_buf_offset));
180 static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
183 struct tls_connection *conn = (struct tls_connection *) ptr;
185 if (wpabuf_resize(&conn->push_buf, len) < 0) {
189 wpabuf_put_data(conn->push_buf, buf, len);
195 static int tls_gnutls_init_session(struct tls_global *global,
196 struct tls_connection *conn)
201 ret = gnutls_init(&conn->session,
202 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
204 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
205 "connection: %s", gnutls_strerror(ret));
209 ret = gnutls_set_default_priority(conn->session);
213 ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
216 wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
221 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
222 gnutls_transport_set_push_function(conn->session, tls_push_func);
223 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
224 gnutls_session_set_ptr(conn->session, conn);
229 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
230 gnutls_strerror(ret));
231 gnutls_deinit(conn->session);
236 struct tls_connection * tls_connection_init(void *ssl_ctx)
238 struct tls_global *global = ssl_ctx;
239 struct tls_connection *conn;
242 conn = os_zalloc(sizeof(*conn));
245 conn->global = global;
247 if (tls_gnutls_init_session(global, conn)) {
252 if (global->params_set) {
253 ret = gnutls_credentials_set(conn->session,
254 GNUTLS_CRD_CERTIFICATE,
257 wpa_printf(MSG_INFO, "Failed to configure "
258 "credentials: %s", gnutls_strerror(ret));
264 if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
273 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
278 gnutls_certificate_free_credentials(conn->xcred);
279 gnutls_deinit(conn->session);
280 os_free(conn->pre_shared_secret);
281 wpabuf_free(conn->push_buf);
282 wpabuf_free(conn->pull_buf);
283 os_free(conn->suffix_match);
284 os_free(conn->domain_match);
289 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
291 return conn ? conn->established : 0;
295 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
297 struct tls_global *global = ssl_ctx;
303 /* Shutdown previous TLS connection without notifying the peer
304 * because the connection was already terminated in practice
305 * and "close notify" shutdown alert would confuse AS. */
306 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
307 wpabuf_free(conn->push_buf);
308 conn->push_buf = NULL;
309 conn->established = 0;
311 gnutls_deinit(conn->session);
312 if (tls_gnutls_init_session(global, conn)) {
313 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
314 "for session resumption use");
318 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
319 conn->params_set ? conn->xcred :
322 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
323 "for session resumption: %s", gnutls_strerror(ret));
327 if (global->session_data) {
328 ret = gnutls_session_set_data(conn->session,
329 global->session_data,
330 global->session_data_size);
332 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
333 "data: %s", gnutls_strerror(ret));
342 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
343 const struct tls_connection_params *params)
347 if (conn == NULL || params == NULL)
350 if (params->subject_match) {
351 wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
355 if (params->altsubject_match) {
356 wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
360 os_free(conn->suffix_match);
361 conn->suffix_match = NULL;
362 if (params->suffix_match) {
363 conn->suffix_match = os_strdup(params->suffix_match);
364 if (conn->suffix_match == NULL)
368 #if GNUTLS_VERSION_NUMBER >= 0x030300
369 os_free(conn->domain_match);
370 conn->domain_match = NULL;
371 if (params->domain_match) {
372 conn->domain_match = os_strdup(params->domain_match);
373 if (conn->domain_match == NULL)
377 if (params->domain_match) {
378 wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
381 #endif /* >= 3.3.0 */
383 conn->flags = params->flags;
385 if (params->openssl_ciphers) {
386 wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
390 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
391 * to force peer validation(?) */
393 if (params->ca_cert) {
394 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
396 ret = gnutls_certificate_set_x509_trust_file(
397 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
399 wpa_printf(MSG_DEBUG,
400 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
402 gnutls_strerror(ret));
403 ret = gnutls_certificate_set_x509_trust_file(
404 conn->xcred, params->ca_cert,
405 GNUTLS_X509_FMT_PEM);
407 wpa_printf(MSG_DEBUG,
408 "Failed to read CA cert '%s' in PEM format: %s",
410 gnutls_strerror(ret));
414 } else if (params->ca_cert_blob) {
417 ca.data = (unsigned char *) params->ca_cert_blob;
418 ca.size = params->ca_cert_blob_len;
420 ret = gnutls_certificate_set_x509_trust_mem(
421 conn->xcred, &ca, GNUTLS_X509_FMT_DER);
423 wpa_printf(MSG_DEBUG,
424 "Failed to parse CA cert in DER format: %s",
425 gnutls_strerror(ret));
426 ret = gnutls_certificate_set_x509_trust_mem(
427 conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
429 wpa_printf(MSG_DEBUG,
430 "Failed to parse CA cert in PEM format: %s",
431 gnutls_strerror(ret));
435 } else if (params->ca_path) {
436 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
440 conn->disable_time_checks = 0;
441 if (params->ca_cert || params->ca_cert_blob) {
442 conn->verify_peer = 1;
443 gnutls_certificate_set_verify_function(
444 conn->xcred, tls_connection_verify_peer);
446 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
447 gnutls_certificate_set_verify_flags(
448 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
451 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
452 conn->disable_time_checks = 1;
453 gnutls_certificate_set_verify_flags(
455 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
459 if (params->client_cert && params->private_key) {
460 #if GNUTLS_VERSION_NUMBER >= 0x03010b
461 ret = gnutls_certificate_set_x509_key_file2(
462 conn->xcred, params->client_cert, params->private_key,
463 GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
465 /* private_key_passwd not (easily) supported here */
466 ret = gnutls_certificate_set_x509_key_file(
467 conn->xcred, params->client_cert, params->private_key,
468 GNUTLS_X509_FMT_DER);
471 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
472 "in DER format: %s", gnutls_strerror(ret));
473 #if GNUTLS_VERSION_NUMBER >= 0x03010b
474 ret = gnutls_certificate_set_x509_key_file2(
475 conn->xcred, params->client_cert,
476 params->private_key, GNUTLS_X509_FMT_PEM,
477 params->private_key_passwd, 0);
479 ret = gnutls_certificate_set_x509_key_file(
480 conn->xcred, params->client_cert,
481 params->private_key, GNUTLS_X509_FMT_PEM);
484 wpa_printf(MSG_DEBUG, "Failed to read client "
485 "cert/key in PEM format: %s",
486 gnutls_strerror(ret));
490 } else if (params->private_key) {
493 /* Try to load in PKCS#12 format */
494 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
495 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
496 params->private_key_passwd);
498 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
499 "PKCS#12 format: %s", gnutls_strerror(ret));
503 #endif /* PKCS12_FUNCS */
506 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
510 } else if (params->client_cert_blob && params->private_key_blob) {
511 gnutls_datum_t cert, key;
513 cert.data = (unsigned char *) params->client_cert_blob;
514 cert.size = params->client_cert_blob_len;
515 key.data = (unsigned char *) params->private_key_blob;
516 key.size = params->private_key_blob_len;
518 #if GNUTLS_VERSION_NUMBER >= 0x03010b
519 ret = gnutls_certificate_set_x509_key_mem2(
520 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
521 params->private_key_passwd, 0);
523 /* private_key_passwd not (easily) supported here */
524 ret = gnutls_certificate_set_x509_key_mem(
525 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
528 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
529 "in DER format: %s", gnutls_strerror(ret));
530 #if GNUTLS_VERSION_NUMBER >= 0x03010b
531 ret = gnutls_certificate_set_x509_key_mem2(
532 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
533 params->private_key_passwd, 0);
535 /* private_key_passwd not (easily) supported here */
536 ret = gnutls_certificate_set_x509_key_mem(
537 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
540 wpa_printf(MSG_DEBUG, "Failed to read client "
541 "cert/key in PEM format: %s",
542 gnutls_strerror(ret));
546 } else if (params->private_key_blob) {
550 key.data = (unsigned char *) params->private_key_blob;
551 key.size = params->private_key_blob_len;
553 /* Try to load in PKCS#12 format */
554 ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
555 conn->xcred, &key, GNUTLS_X509_FMT_DER,
556 params->private_key_passwd);
558 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
559 "PKCS#12 format: %s", gnutls_strerror(ret));
562 #else /* PKCS12_FUNCS */
563 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
565 #endif /* PKCS12_FUNCS */
568 #if GNUTLS_VERSION_NUMBER >= 0x030103
569 if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
570 ret = gnutls_ocsp_status_request_enable_client(conn->session,
572 if (ret != GNUTLS_E_SUCCESS) {
574 "GnuTLS: Failed to enable OCSP client");
579 if (params->flags & TLS_CONN_REQUIRE_OCSP) {
581 "GnuTLS: OCSP not supported by this version of GnuTLS");
586 conn->params_set = 1;
588 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
591 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
592 gnutls_strerror(ret));
599 int tls_global_set_params(void *tls_ctx,
600 const struct tls_connection_params *params)
602 struct tls_global *global = tls_ctx;
605 /* Currently, global parameters are only set when running in server
609 if (global->params_set) {
610 gnutls_certificate_free_credentials(global->xcred);
611 global->params_set = 0;
614 ret = gnutls_certificate_allocate_credentials(&global->xcred);
616 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
617 "%s", gnutls_strerror(ret));
621 if (params->ca_cert) {
622 ret = gnutls_certificate_set_x509_trust_file(
623 global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
625 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
626 "in DER format: %s", params->ca_cert,
627 gnutls_strerror(ret));
628 ret = gnutls_certificate_set_x509_trust_file(
629 global->xcred, params->ca_cert,
630 GNUTLS_X509_FMT_PEM);
632 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
633 "'%s' in PEM format: %s",
635 gnutls_strerror(ret));
640 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
641 gnutls_certificate_set_verify_flags(
643 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
646 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
647 gnutls_certificate_set_verify_flags(
649 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
653 if (params->client_cert && params->private_key) {
654 /* TODO: private_key_passwd? */
655 ret = gnutls_certificate_set_x509_key_file(
656 global->xcred, params->client_cert,
657 params->private_key, GNUTLS_X509_FMT_DER);
659 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
660 "in DER format: %s", gnutls_strerror(ret));
661 ret = gnutls_certificate_set_x509_key_file(
662 global->xcred, params->client_cert,
663 params->private_key, GNUTLS_X509_FMT_PEM);
665 wpa_printf(MSG_DEBUG, "Failed to read client "
666 "cert/key in PEM format: %s",
667 gnutls_strerror(ret));
671 } else if (params->private_key) {
674 /* Try to load in PKCS#12 format */
675 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
676 global->xcred, params->private_key,
677 GNUTLS_X509_FMT_DER, params->private_key_passwd);
679 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
680 "PKCS#12 format: %s", gnutls_strerror(ret));
684 #endif /* PKCS12_FUNCS */
687 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
693 global->params_set = 1;
698 gnutls_certificate_free_credentials(global->xcred);
703 int tls_global_set_verify(void *ssl_ctx, int check_crl)
710 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
713 if (conn == NULL || conn->session == NULL)
716 conn->verify_peer = verify_peer;
717 gnutls_certificate_server_set_request(conn->session,
718 verify_peer ? GNUTLS_CERT_REQUIRE
719 : GNUTLS_CERT_REQUEST);
725 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
726 struct tls_keys *keys)
728 #if GNUTLS_VERSION_NUMBER >= 0x030012
729 gnutls_datum_t client, server;
731 if (conn == NULL || conn->session == NULL || keys == NULL)
734 os_memset(keys, 0, sizeof(*keys));
735 gnutls_session_get_random(conn->session, &client, &server);
736 keys->client_random = client.data;
737 keys->server_random = server.data;
738 keys->client_random_len = client.size;
739 keys->server_random_len = client.size;
748 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
749 const char *label, int server_random_first,
750 u8 *out, size_t out_len)
752 if (conn == NULL || conn->session == NULL)
755 return gnutls_prf(conn->session, os_strlen(label), label,
756 server_random_first, 0, NULL, out_len, (char *) out);
760 static void gnutls_tls_fail_event(struct tls_connection *conn,
761 const gnutls_datum_t *cert, int depth,
762 const char *subject, const char *err_str,
763 enum tls_fail_reason reason)
765 union tls_event_data ev;
766 struct tls_global *global = conn->global;
767 struct wpabuf *cert_buf = NULL;
769 if (global->event_cb == NULL)
772 os_memset(&ev, 0, sizeof(ev));
773 ev.cert_fail.depth = depth;
774 ev.cert_fail.subject = subject ? subject : "";
775 ev.cert_fail.reason = reason;
776 ev.cert_fail.reason_txt = err_str;
778 cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
779 ev.cert_fail.cert = cert_buf;
781 global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
782 wpabuf_free(cert_buf);
786 #if GNUTLS_VERSION_NUMBER < 0x030300
787 static int server_eku_purpose(gnutls_x509_crt_t cert)
793 size_t oid_size = sizeof(oid);
796 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
798 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
800 /* No EKU - assume any use allowed */
807 wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
811 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
812 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
813 os_strcmp(oid, GNUTLS_KP_ANY) == 0)
822 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
823 gnutls_alert_description_t *err)
825 #if GNUTLS_VERSION_NUMBER >= 0x030103
826 gnutls_datum_t response, buf;
827 gnutls_ocsp_resp_t resp;
828 unsigned int cert_status;
831 if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
834 if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
835 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
837 "GnuTLS: No valid OCSP response received");
841 wpa_printf(MSG_DEBUG,
842 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
847 * GnuTLS has already verified the OCSP response in
848 * check_ocsp_response() and rejected handshake if the certificate was
849 * found to be revoked. However, if the response indicates that the
850 * status is unknown, handshake continues and reaches here. We need to
851 * re-import the OCSP response to check for unknown certificate status,
852 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
853 * gnutls_ocsp_resp_verify_direct() calls.
856 res = gnutls_ocsp_status_request_get(session, &response);
857 if (res != GNUTLS_E_SUCCESS) {
859 "GnuTLS: OCSP response was received, but it was not valid");
863 if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
866 res = gnutls_ocsp_resp_import(resp, &response);
867 if (res != GNUTLS_E_SUCCESS) {
869 "GnuTLS: Could not parse received OCSP response: %s",
870 gnutls_strerror(res));
871 gnutls_ocsp_resp_deinit(resp);
875 res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
876 if (res == GNUTLS_E_SUCCESS) {
877 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
878 gnutls_free(buf.data);
881 res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
882 NULL, &cert_status, NULL,
884 gnutls_ocsp_resp_deinit(resp);
885 if (res != GNUTLS_E_SUCCESS) {
887 "GnuTLS: Failed to extract OCSP information: %s",
888 gnutls_strerror(res));
892 if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
893 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
894 } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
895 wpa_printf(MSG_DEBUG,
896 "GnuTLS: OCSP cert status: revoked");
899 wpa_printf(MSG_DEBUG,
900 "GnuTLS: OCSP cert status: unknown");
901 if (conn->flags & TLS_CONN_REQUIRE_OCSP)
903 wpa_printf(MSG_DEBUG,
904 "GnuTLS: OCSP was not required, so allow connection to continue");
910 gnutls_tls_fail_event(conn, NULL, 0, NULL,
911 "bad certificate status response",
913 *err = GNUTLS_A_CERTIFICATE_REVOKED;
915 #else /* GnuTLS 3.1.3 or newer */
917 #endif /* GnuTLS 3.1.3 or newer */
921 static int tls_connection_verify_peer(gnutls_session_t session)
923 struct tls_connection *conn;
924 unsigned int status, num_certs, i;
926 const gnutls_datum_t *certs;
927 gnutls_x509_crt_t cert;
928 gnutls_alert_description_t err;
931 conn = gnutls_session_get_ptr(session);
932 if (!conn->verify_peer) {
933 wpa_printf(MSG_DEBUG,
934 "GnuTLS: No peer certificate verification enabled");
938 wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
940 #if GNUTLS_VERSION_NUMBER >= 0x030300
942 gnutls_typed_vdata_st data[1];
943 unsigned int elements = 0;
945 os_memset(data, 0, sizeof(data));
946 if (!conn->global->server) {
947 data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
948 data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
951 res = gnutls_certificate_verify_peers(session, data, 1,
955 res = gnutls_certificate_verify_peers2(session, &status);
958 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
959 "certificate chain");
960 err = GNUTLS_A_INTERNAL_ERROR;
964 #if GNUTLS_VERSION_NUMBER >= 0x030104
969 type = gnutls_certificate_type_get(session);
970 ret = gnutls_certificate_verification_status_print(status, type,
973 wpa_printf(MSG_DEBUG,
974 "GnuTLS: Failed to print verification status");
975 err = GNUTLS_A_INTERNAL_ERROR;
978 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
979 gnutls_free(info.data);
981 #endif /* GnuTLS 3.1.4 or newer */
983 certs = gnutls_certificate_get_peers(session, &num_certs);
984 if (certs == NULL || num_certs == 0) {
985 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
986 err = GNUTLS_A_UNKNOWN_CA;
990 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
991 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
992 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
993 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
995 gnutls_tls_fail_event(conn, NULL, 0, NULL,
996 "certificate uses insecure algorithm",
997 TLS_FAIL_BAD_CERTIFICATE);
998 err = GNUTLS_A_INSUFFICIENT_SECURITY;
1001 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1002 wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1004 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1005 "certificate not yet valid",
1006 TLS_FAIL_NOT_YET_VALID);
1007 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1010 if (status & GNUTLS_CERT_EXPIRED) {
1011 wpa_printf(MSG_INFO, "TLS: Certificate expired");
1012 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1013 "certificate has expired",
1015 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1018 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1019 "untrusted certificate",
1020 TLS_FAIL_UNTRUSTED);
1021 err = GNUTLS_A_INTERNAL_ERROR;
1025 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1026 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1028 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1029 TLS_FAIL_UNTRUSTED);
1030 err = GNUTLS_A_UNKNOWN_CA;
1034 if (status & GNUTLS_CERT_REVOKED) {
1035 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1036 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1037 "certificate revoked",
1039 err = GNUTLS_A_CERTIFICATE_REVOKED;
1044 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1046 err = GNUTLS_A_INTERNAL_ERROR;
1050 if (check_ocsp(conn, session, &err))
1055 for (i = 0; i < num_certs; i++) {
1058 if (gnutls_x509_crt_init(&cert) < 0) {
1059 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1061 err = GNUTLS_A_BAD_CERTIFICATE;
1065 if (gnutls_x509_crt_import(cert, &certs[i],
1066 GNUTLS_X509_FMT_DER) < 0) {
1067 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1068 "certificate %d/%d", i + 1, num_certs);
1069 gnutls_x509_crt_deinit(cert);
1070 err = GNUTLS_A_BAD_CERTIFICATE;
1074 gnutls_x509_crt_get_dn(cert, NULL, &len);
1076 buf = os_malloc(len + 1);
1078 buf[0] = buf[len] = '\0';
1079 gnutls_x509_crt_get_dn(cert, buf, &len);
1081 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1082 i + 1, num_certs, buf);
1084 if (conn->global->event_cb) {
1085 struct wpabuf *cert_buf = NULL;
1086 union tls_event_data ev;
1087 #ifdef CONFIG_SHA256
1091 #endif /* CONFIG_SHA256 */
1093 os_memset(&ev, 0, sizeof(ev));
1094 if (conn->global->cert_in_cb) {
1095 cert_buf = wpabuf_alloc_copy(certs[i].data,
1097 ev.peer_cert.cert = cert_buf;
1099 #ifdef CONFIG_SHA256
1100 _addr[0] = certs[i].data;
1101 _len[0] = certs[i].size;
1102 if (sha256_vector(1, _addr, _len, hash) == 0) {
1103 ev.peer_cert.hash = hash;
1104 ev.peer_cert.hash_len = sizeof(hash);
1106 #endif /* CONFIG_SHA256 */
1107 ev.peer_cert.depth = i;
1108 ev.peer_cert.subject = buf;
1109 conn->global->event_cb(conn->global->cb_ctx,
1110 TLS_PEER_CERTIFICATE, &ev);
1111 wpabuf_free(cert_buf);
1115 if (conn->suffix_match &&
1116 !gnutls_x509_crt_check_hostname(
1117 cert, conn->suffix_match)) {
1118 wpa_printf(MSG_WARNING,
1119 "TLS: Domain suffix match '%s' not found",
1120 conn->suffix_match);
1121 gnutls_tls_fail_event(
1122 conn, &certs[i], i, buf,
1123 "Domain suffix mismatch",
1124 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1125 err = GNUTLS_A_BAD_CERTIFICATE;
1126 gnutls_x509_crt_deinit(cert);
1131 #if GNUTLS_VERSION_NUMBER >= 0x030300
1132 if (conn->domain_match &&
1133 !gnutls_x509_crt_check_hostname2(
1134 cert, conn->domain_match,
1135 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
1136 wpa_printf(MSG_WARNING,
1137 "TLS: Domain match '%s' not found",
1138 conn->domain_match);
1139 gnutls_tls_fail_event(
1140 conn, &certs[i], i, buf,
1142 TLS_FAIL_DOMAIN_MISMATCH);
1143 err = GNUTLS_A_BAD_CERTIFICATE;
1144 gnutls_x509_crt_deinit(cert);
1148 #endif /* >= 3.3.0 */
1150 /* TODO: validate altsubject_match.
1151 * For now, any such configuration is rejected in
1152 * tls_connection_set_params() */
1154 #if GNUTLS_VERSION_NUMBER < 0x030300
1156 * gnutls_certificate_verify_peers() not available, so
1157 * need to check EKU separately.
1159 if (!conn->global->server &&
1160 !server_eku_purpose(cert)) {
1161 wpa_printf(MSG_WARNING,
1162 "GnuTLS: No server EKU");
1163 gnutls_tls_fail_event(
1164 conn, &certs[i], i, buf,
1166 TLS_FAIL_BAD_CERTIFICATE);
1167 err = GNUTLS_A_BAD_CERTIFICATE;
1168 gnutls_x509_crt_deinit(cert);
1172 #endif /* < 3.3.0 */
1175 if (!conn->disable_time_checks &&
1176 (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1177 gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1178 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1179 "not valid at this time",
1181 gnutls_tls_fail_event(
1182 conn, &certs[i], i, buf,
1183 "Certificate is not valid at this time",
1185 gnutls_x509_crt_deinit(cert);
1187 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1193 gnutls_x509_crt_deinit(cert);
1196 if (conn->global->event_cb != NULL)
1197 conn->global->event_cb(conn->global->cb_ctx,
1198 TLS_CERT_CHAIN_SUCCESS, NULL);
1204 gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1205 return GNUTLS_E_CERTIFICATE_ERROR;
1209 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1213 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1214 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1218 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1220 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1222 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1223 "(%s)", __func__, (int) res,
1224 gnutls_strerror(res));
1229 wpabuf_put(ad, res);
1230 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1236 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1237 struct tls_connection *conn,
1238 const struct wpabuf *in_data,
1239 struct wpabuf **appl_data)
1241 struct tls_global *global = tls_ctx;
1242 struct wpabuf *out_data;
1248 if (in_data && wpabuf_len(in_data) > 0) {
1249 if (conn->pull_buf) {
1250 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1251 "pull_buf", __func__,
1252 (unsigned long) wpabuf_len(conn->pull_buf));
1253 wpabuf_free(conn->pull_buf);
1255 conn->pull_buf = wpabuf_dup(in_data);
1256 if (conn->pull_buf == NULL)
1258 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1261 ret = gnutls_handshake(conn->session);
1263 gnutls_alert_description_t alert;
1266 case GNUTLS_E_AGAIN:
1267 if (global->server && conn->established &&
1268 conn->push_buf == NULL) {
1269 /* Need to return something to trigger
1270 * completion of EAP-TLS. */
1271 conn->push_buf = wpabuf_alloc(0);
1274 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1275 alert = gnutls_alert_get(conn->session);
1276 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1277 __func__, gnutls_alert_get_name(alert));
1278 conn->read_alerts++;
1279 if (conn->global->event_cb != NULL) {
1280 union tls_event_data ev;
1282 os_memset(&ev, 0, sizeof(ev));
1283 ev.alert.is_local = 0;
1284 ev.alert.type = gnutls_alert_get_name(alert);
1285 ev.alert.description = ev.alert.type;
1286 conn->global->event_cb(conn->global->cb_ctx,
1291 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1292 "-> %s", __func__, gnutls_strerror(ret));
1298 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1300 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1304 desc = gnutls_session_get_desc(conn->session);
1306 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1310 #endif /* GnuTLS 3.1.10 or newer */
1312 conn->established = 1;
1313 if (conn->push_buf == NULL) {
1314 /* Need to return something to get final TLS ACK. */
1315 conn->push_buf = wpabuf_alloc(0);
1318 gnutls_session_get_data(conn->session, NULL, &size);
1319 if (global->session_data == NULL ||
1320 global->session_data_size < size) {
1321 os_free(global->session_data);
1322 global->session_data = os_malloc(size);
1324 if (global->session_data) {
1325 global->session_data_size = size;
1326 gnutls_session_get_data(conn->session,
1327 global->session_data,
1328 &global->session_data_size);
1331 if (conn->pull_buf && appl_data)
1332 *appl_data = gnutls_get_appl_data(conn);
1335 out_data = conn->push_buf;
1336 conn->push_buf = NULL;
1341 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1342 struct tls_connection *conn,
1343 const struct wpabuf *in_data,
1344 struct wpabuf **appl_data)
1346 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1350 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1351 struct tls_connection *conn,
1352 const struct wpabuf *in_data)
1357 res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1358 wpabuf_len(in_data));
1360 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1361 __func__, gnutls_strerror(res));
1365 buf = conn->push_buf;
1366 conn->push_buf = NULL;
1371 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1372 struct tls_connection *conn,
1373 const struct wpabuf *in_data)
1378 if (conn->pull_buf) {
1379 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1380 "pull_buf", __func__,
1381 (unsigned long) wpabuf_len(conn->pull_buf));
1382 wpabuf_free(conn->pull_buf);
1384 conn->pull_buf = wpabuf_dup(in_data);
1385 if (conn->pull_buf == NULL)
1387 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1390 * Even though we try to disable TLS compression, it is possible that
1391 * this cannot be done with all TLS libraries. Add extra buffer space
1392 * to handle the possibility of the decrypted data being longer than
1395 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1399 res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1402 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1403 "(%s)", __func__, (int) res, gnutls_strerror(res));
1407 wpabuf_put(out, res);
1413 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1417 return gnutls_session_is_resumed(conn->session);
1421 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1429 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1430 char *buf, size_t buflen)
1438 int tls_connection_enable_workaround(void *ssl_ctx,
1439 struct tls_connection *conn)
1441 gnutls_record_disable_padding(conn->session);
1446 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1447 int ext_type, const u8 *data,
1455 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1459 return conn->failed;
1463 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1467 return conn->read_alerts;
1471 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1475 return conn->write_alerts;
1479 int tls_connection_get_keyblock_size(void *tls_ctx,
1480 struct tls_connection *conn)
1487 unsigned int tls_capabilities(void *tls_ctx)
1493 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1494 struct tls_connection *conn,
1495 tls_session_ticket_cb cb, void *ctx)
1501 int tls_get_library_version(char *buf, size_t buf_len)
1503 return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1504 GNUTLS_VERSION, gnutls_check_version(NULL));