Lines Matching +full:check +full:- +full:crypto +full:- +full:only +full:- +full:gnutls
2 * QEMU crypto TLS session support
22 #include "qemu/error-report.h"
24 #include "crypto/tlssession.h"
25 #include "crypto/tlscredsanon.h"
26 #include "crypto/tlscredspsk.h"
27 #include "crypto/tlscredsx509.h"
36 #include <gnutls/x509.h>
58 * Used to protect against broken GNUTLS thread safety
59 * https://gitlab.com/gnutls/gnutls/-/issues/1717
74 error_free(session->rerr); in qcrypto_tls_session_free()
75 error_free(session->werr); in qcrypto_tls_session_free()
77 gnutls_deinit(session->handle); in qcrypto_tls_session_free()
78 g_free(session->hostname); in qcrypto_tls_session_free()
79 g_free(session->peername); in qcrypto_tls_session_free()
80 g_free(session->authzid); in qcrypto_tls_session_free()
81 object_unref(OBJECT(session->creds)); in qcrypto_tls_session_free()
82 qemu_mutex_destroy(&session->lock); in qcrypto_tls_session_free()
93 if (!session->writeFunc) { in qcrypto_tls_session_push()
95 return -1; in qcrypto_tls_session_push()
98 if (session->lockEnabled) { in qcrypto_tls_session_push()
99 qemu_mutex_unlock(&session->lock); in qcrypto_tls_session_push()
102 error_free(session->werr); in qcrypto_tls_session_push()
103 session->werr = NULL; in qcrypto_tls_session_push()
105 ret = session->writeFunc(buf, len, session->opaque, &session->werr); in qcrypto_tls_session_push()
107 if (session->lockEnabled) { in qcrypto_tls_session_push()
108 qemu_mutex_lock(&session->lock); in qcrypto_tls_session_push()
113 return -1; in qcrypto_tls_session_push()
116 return -1; in qcrypto_tls_session_push()
129 if (!session->readFunc) { in qcrypto_tls_session_pull()
131 return -1; in qcrypto_tls_session_pull()
134 error_free(session->rerr); in qcrypto_tls_session_pull()
135 session->rerr = NULL; in qcrypto_tls_session_pull()
137 if (session->lockEnabled) { in qcrypto_tls_session_pull()
138 qemu_mutex_unlock(&session->lock); in qcrypto_tls_session_pull()
141 ret = session->readFunc(buf, len, session->opaque, &session->rerr); in qcrypto_tls_session_pull()
143 if (session->lockEnabled) { in qcrypto_tls_session_pull()
144 qemu_mutex_lock(&session->lock); in qcrypto_tls_session_pull()
149 return -1; in qcrypto_tls_session_pull()
152 return -1; in qcrypto_tls_session_pull()
158 #define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH"
159 #define TLS_PRIORITY_ADDITIONAL_PSK "+ECDHE-PSK:+DHE-PSK:+PSK"
177 session->hostname = g_strdup(hostname); in qcrypto_tls_session_new()
180 session->authzid = g_strdup(authzid); in qcrypto_tls_session_new()
182 session->creds = creds; in qcrypto_tls_session_new()
185 qemu_mutex_init(&session->lock); in qcrypto_tls_session_new()
187 if (creds->endpoint != endpoint) { in qcrypto_tls_session_new()
193 ret = gnutls_init(&session->handle, GNUTLS_SERVER); in qcrypto_tls_session_new()
195 ret = gnutls_init(&session->handle, GNUTLS_CLIENT); in qcrypto_tls_session_new()
208 if (creds->priority != NULL) { in qcrypto_tls_session_new()
210 creds->priority, in qcrypto_tls_session_new()
217 ret = gnutls_priority_set_direct(session->handle, prio, NULL); in qcrypto_tls_session_new()
225 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { in qcrypto_tls_session_new()
226 ret = gnutls_credentials_set(session->handle, in qcrypto_tls_session_new()
228 acreds->data.server); in qcrypto_tls_session_new()
230 ret = gnutls_credentials_set(session->handle, in qcrypto_tls_session_new()
232 acreds->data.client); in qcrypto_tls_session_new()
244 if (creds->priority != NULL) { in qcrypto_tls_session_new()
246 creds->priority, in qcrypto_tls_session_new()
253 ret = gnutls_priority_set_direct(session->handle, prio, NULL); in qcrypto_tls_session_new()
261 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { in qcrypto_tls_session_new()
262 ret = gnutls_credentials_set(session->handle, in qcrypto_tls_session_new()
264 pcreds->data.server); in qcrypto_tls_session_new()
266 ret = gnutls_credentials_set(session->handle, in qcrypto_tls_session_new()
268 pcreds->data.client); in qcrypto_tls_session_new()
278 const char *prio = creds->priority; in qcrypto_tls_session_new()
283 ret = gnutls_priority_set_direct(session->handle, prio, NULL); in qcrypto_tls_session_new()
289 ret = gnutls_credentials_set(session->handle, in qcrypto_tls_session_new()
291 tcreds->data); in qcrypto_tls_session_new()
298 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { in qcrypto_tls_session_new()
301 gnutls_certificate_server_set_request(session->handle, in qcrypto_tls_session_new()
310 gnutls_transport_set_ptr(session->handle, session); in qcrypto_tls_session_new()
311 gnutls_transport_set_push_function(session->handle, in qcrypto_tls_session_new()
313 gnutls_transport_set_pull_function(session->handle, in qcrypto_tls_session_new()
325 sess->requireThreadSafety = true; in qcrypto_tls_session_require_thread_safety()
341 if (now == ((time_t)-1)) { in qcrypto_tls_session_check_certificate()
343 return -1; in qcrypto_tls_session_check_certificate()
346 ret = gnutls_certificate_verify_peers2(session->handle, &status); in qcrypto_tls_session_check_certificate()
349 return -1; in qcrypto_tls_session_check_certificate()
372 return -1; in qcrypto_tls_session_check_certificate()
375 certs = gnutls_certificate_get_peers(session->handle, &nCerts); in qcrypto_tls_session_check_certificate()
378 return -1; in qcrypto_tls_session_check_certificate()
386 return -1; in qcrypto_tls_session_check_certificate()
413 session->peername = g_malloc(dnameSize); in qcrypto_tls_session_check_certificate()
415 ret = gnutls_x509_crt_get_dn(cert, session->peername, &dnameSize); in qcrypto_tls_session_check_certificate()
418 session->peername = g_realloc(session->peername, in qcrypto_tls_session_check_certificate()
426 if (session->authzid) { in qcrypto_tls_session_check_certificate()
429 allow = qauthz_is_allowed_by_id(session->authzid, in qcrypto_tls_session_check_certificate()
430 session->peername, &err); in qcrypto_tls_session_check_certificate()
436 error_setg(errp, "TLS x509 authz check for %s is denied", in qcrypto_tls_session_check_certificate()
437 session->peername); in qcrypto_tls_session_check_certificate()
441 if (session->hostname) { in qcrypto_tls_session_check_certificate()
442 if (!gnutls_x509_crt_check_hostname(cert, session->hostname)) { in qcrypto_tls_session_check_certificate()
445 session->hostname); in qcrypto_tls_session_check_certificate()
449 if (session->creds->endpoint == in qcrypto_tls_session_check_certificate()
464 return -1; in qcrypto_tls_session_check_certificate()
472 if (object_dynamic_cast(OBJECT(session->creds), in qcrypto_tls_session_check_credentials()
476 } else if (object_dynamic_cast(OBJECT(session->creds), in qcrypto_tls_session_check_credentials()
480 } else if (object_dynamic_cast(OBJECT(session->creds), in qcrypto_tls_session_check_credentials()
482 if (session->creds->verifyPeer) { in qcrypto_tls_session_check_credentials()
495 object_get_typename(OBJECT(session->creds))); in qcrypto_tls_session_check_credentials()
496 return -1; in qcrypto_tls_session_check_credentials()
507 session->writeFunc = writeFunc; in qcrypto_tls_session_set_callbacks()
508 session->readFunc = readFunc; in qcrypto_tls_session_set_callbacks()
509 session->opaque = opaque; in qcrypto_tls_session_set_callbacks()
521 if (session->lockEnabled) { in qcrypto_tls_session_write()
522 qemu_mutex_lock(&session->lock); in qcrypto_tls_session_write()
525 ret = gnutls_record_send(session->handle, buf, len); in qcrypto_tls_session_write()
527 if (session->lockEnabled) { in qcrypto_tls_session_write()
528 qemu_mutex_unlock(&session->lock); in qcrypto_tls_session_write()
535 if (session->werr) { in qcrypto_tls_session_write()
536 error_propagate(errp, session->werr); in qcrypto_tls_session_write()
537 session->werr = NULL; in qcrypto_tls_session_write()
543 return -1; in qcrypto_tls_session_write()
560 if (session->lockEnabled) { in qcrypto_tls_session_read()
561 qemu_mutex_lock(&session->lock); in qcrypto_tls_session_read()
564 ret = gnutls_record_recv(session->handle, buf, len); in qcrypto_tls_session_read()
566 if (session->lockEnabled) { in qcrypto_tls_session_read()
567 qemu_mutex_unlock(&session->lock); in qcrypto_tls_session_read()
577 if (session->rerr) { in qcrypto_tls_session_read()
578 error_propagate(errp, session->rerr); in qcrypto_tls_session_read()
579 session->rerr = NULL; in qcrypto_tls_session_read()
585 return -1; in qcrypto_tls_session_read()
596 return gnutls_record_check_pending(session->handle); in qcrypto_tls_session_check_pending()
605 ret = gnutls_handshake(session->handle); in qcrypto_tls_session_handshake()
610 gnutls_cipher_get(session->handle); in qcrypto_tls_session_handshake()
614 * a gnutls with bug 1717, however, we know that in qcrypto_tls_session_handshake()
616 * only have to protect against automatic rekeying in qcrypto_tls_session_handshake()
621 session->requireThreadSafety, in qcrypto_tls_session_handshake()
622 gnutls_protocol_get_version(session->handle), in qcrypto_tls_session_handshake()
625 if (session->requireThreadSafety && in qcrypto_tls_session_handshake()
626 gnutls_protocol_get_version(session->handle) == in qcrypto_tls_session_handshake()
630 "for potentially broken GNUTLS with TLS1.3 cipher=%d", in qcrypto_tls_session_handshake()
633 session->lockEnabled = true; in qcrypto_tls_session_handshake()
637 session->handshakeComplete = true; in qcrypto_tls_session_handshake()
642 int direction = gnutls_record_get_direction(session->handle); in qcrypto_tls_session_handshake()
647 if (session->rerr || session->werr) { in qcrypto_tls_session_handshake()
650 error_get_pretty(session->rerr ? in qcrypto_tls_session_handshake()
651 session->rerr : session->werr)); in qcrypto_tls_session_handshake()
657 error_free(session->rerr); in qcrypto_tls_session_handshake()
658 error_free(session->werr); in qcrypto_tls_session_handshake()
659 session->rerr = session->werr = NULL; in qcrypto_tls_session_handshake()
661 return -1; in qcrypto_tls_session_handshake()
670 if (!session->handshakeComplete) { in qcrypto_tls_session_bye()
674 if (session->lockEnabled) { in qcrypto_tls_session_bye()
675 qemu_mutex_lock(&session->lock); in qcrypto_tls_session_bye()
677 ret = gnutls_bye(session->handle, GNUTLS_SHUT_WR); in qcrypto_tls_session_bye()
679 if (session->lockEnabled) { in qcrypto_tls_session_bye()
680 qemu_mutex_unlock(&session->lock); in qcrypto_tls_session_bye()
688 int direction = gnutls_record_get_direction(session->handle); in qcrypto_tls_session_bye()
692 if (session->rerr || session->werr) { in qcrypto_tls_session_bye()
694 error_get_pretty(session->rerr ? in qcrypto_tls_session_bye()
695 session->rerr : session->werr)); in qcrypto_tls_session_bye()
700 error_free(session->rerr); in qcrypto_tls_session_bye()
701 error_free(session->werr); in qcrypto_tls_session_bye()
702 session->rerr = session->werr = NULL; in qcrypto_tls_session_bye()
704 return -1; in qcrypto_tls_session_bye()
714 cipher = gnutls_cipher_get(session->handle); in qcrypto_tls_session_get_key_size()
718 return -1; in qcrypto_tls_session_get_key_size()
727 if (session->peername) { in qcrypto_tls_session_get_peer_name()
728 return g_strdup(session->peername); in qcrypto_tls_session_get_peer_name()
744 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_new()
762 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_check_credentials()
763 return -1; in qcrypto_tls_session_check_credentials()
783 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_write()
784 return -1; in qcrypto_tls_session_write()
795 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_read()
796 return -1; in qcrypto_tls_session_read()
811 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_handshake()
812 return -1; in qcrypto_tls_session_handshake()
827 error_setg(errp, "TLS requires GNUTLS support"); in qcrypto_tls_session_get_key_size()
828 return -1; in qcrypto_tls_session_get_key_size()