public inbox for kernel-tls-handshake@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake
@ 2025-09-25 16:38 Xin Long
  2025-09-25 16:38 ` [PATCH 1/2] tlshd: leave session_status as EIO on GnuTLS failure in QUIC session setup Xin Long
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Xin Long @ 2025-09-25 16:38 UTC (permalink / raw)
  To: kernel-tls-handshake; +Cc: Chuck Lever

This series aligns QUIC error handling in tlshd with the TLS 1.3 code.

- On GnuTLS failure during session setup, log the error and leave
  parms session_status = EIO.

- On GnuTLS failure during handshake, log the error and set conn
  errcode = EACCES.

Xin Long (2):
  tlshd: leave session_status as EIO on GnuTLS failure in QUIC session
    setup
  tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake

 src/tlshd/client.c | 42 ++++++++++++++---------------
 src/tlshd/quic.c   | 66 ++++++++++++++++++++++++++--------------------
 src/tlshd/server.c | 29 +++++++++-----------
 3 files changed, 70 insertions(+), 67 deletions(-)

-- 
2.47.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] tlshd: leave session_status as EIO on GnuTLS failure in QUIC session setup
  2025-09-25 16:38 [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake Xin Long
@ 2025-09-25 16:38 ` Xin Long
  2025-09-25 16:38 ` [PATCH 2/2] tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake Xin Long
  2025-09-26 13:14 ` [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors " Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Xin Long @ 2025-09-25 16:38 UTC (permalink / raw)
  To: kernel-tls-handshake; +Cc: Chuck Lever

Align the QUIC session setup error handling with the TLS 1.3 code paths:

- tlshd_tls13_client_x509_handshake()
- tlshd_tls13_client_psk_handshake()
- tlshd_tls13_server_x509_handshake()
- tlshd_tls13_server_psk_handshake()

The QUIC session setup functions:

- tlshd_quic_client_set_x509_session()
- tlshd_quic_client_set_psk_session()
- tlshd_quic_server_set_x509_session()
- tlshd_quic_server_set_psk_session()

will no longer return an error directly. Instead, if a GnuTLS API call
fails, session_status is left as EIO after logging the Gnutls errors.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 src/tlshd/client.c | 42 ++++++++++++++++++++----------------------
 src/tlshd/server.c | 29 +++++++++++++----------------
 2 files changed, 33 insertions(+), 38 deletions(-)

diff --git a/src/tlshd/client.c b/src/tlshd/client.c
index ad9a793..3415fdd 100644
--- a/src/tlshd/client.c
+++ b/src/tlshd/client.c
@@ -530,17 +530,17 @@ static int tlshd_quic_client_x509_verify_function(gnutls_session_t session)
 
 #define TLSHD_QUIC_NO_CERT_AUTH	3
 
-static int tlshd_quic_client_set_x509_session(struct tlshd_quic_conn *conn)
+static void tlshd_quic_client_set_x509_session(struct tlshd_quic_conn *conn)
 {
 	struct tlshd_handshake_parms *parms = conn->parms;
 	gnutls_certificate_credentials_t cred;
 	gnutls_session_t session;
-	int ret = -EINVAL;
+	int ret;
 
 	if (conn->cert_req != TLSHD_QUIC_NO_CERT_AUTH) {
 		if (!tlshd_x509_client_get_certs(parms) || !tlshd_x509_client_get_privkey(parms)) {
-			tlshd_log_error("cert/privkey get error %d", -ret);
-			return ret;
+			tlshd_log_error("Failed to get cert or privkey");
+			return;
 		}
 	}
 	ret = gnutls_certificate_allocate_credentials(&cred);
@@ -581,7 +581,8 @@ static int tlshd_quic_client_set_x509_session(struct tlshd_quic_conn *conn)
 			goto err_session;
 	}
 	conn->session = session;
-	return 0;
+	return;
+
 err_session:
 	gnutls_deinit(session);
 err_cred:
@@ -590,29 +591,28 @@ err:
 	tlshd_x509_client_put_privkey();
 	tlshd_x509_client_put_certs();
 	tlshd_log_gnutls_error(ret);
-	return ret;
 }
 
-static int tlshd_quic_client_set_anon_session(struct tlshd_quic_conn *conn)
+static void tlshd_quic_client_set_anon_session(struct tlshd_quic_conn *conn)
 {
 	conn->cert_req = TLSHD_QUIC_NO_CERT_AUTH;
-	return tlshd_quic_client_set_x509_session(conn);
+	tlshd_quic_client_set_x509_session(conn);
 }
 
-static int tlshd_quic_client_set_psk_session(struct tlshd_quic_conn *conn)
+static void tlshd_quic_client_set_psk_session(struct tlshd_quic_conn *conn)
 {
 	key_serial_t peerid = g_array_index(conn->parms->peerids, key_serial_t, 0);
 	gnutls_psk_client_credentials_t cred;
 	gnutls_session_t session;
 	char *identity = NULL;
 	gnutls_datum_t key;
-	int ret = -EINVAL;
+	int ret;
 
 	if (!tlshd_keyring_get_psk_username(peerid, &identity) ||
 	    !tlshd_keyring_get_psk_key(peerid, &key)) {
 		free(identity);
-		tlshd_log_error("identity/key get error %d", -ret);
-		return ret;
+		tlshd_log_error("Failed to get key identity or read key");
+		return;
 	}
 
 	ret = gnutls_psk_allocate_client_credentials(&cred);
@@ -630,7 +630,8 @@ static int tlshd_quic_client_set_psk_session(struct tlshd_quic_conn *conn)
 	if (ret)
 		goto err_session;
 	conn->session = session;
-	return 0;
+	return;
+
 err_session:
 	gnutls_deinit(session);
 err_cred:
@@ -638,7 +639,6 @@ err_cred:
 err:
 	free(identity);
 	tlshd_log_gnutls_error(ret);
-	return ret;
 }
 
 /**
@@ -659,26 +659,24 @@ void tlshd_quic_clienthello_handshake(struct tlshd_handshake_parms *parms)
 
 	switch (parms->auth_mode) {
 	case HANDSHAKE_AUTH_UNAUTH:
-		ret = tlshd_quic_client_set_anon_session(conn);
+		tlshd_quic_client_set_anon_session(conn);
 		break;
 	case HANDSHAKE_AUTH_X509:
-		ret = tlshd_quic_client_set_x509_session(conn);
+		tlshd_quic_client_set_x509_session(conn);
 		break;
 	case HANDSHAKE_AUTH_PSK:
-		ret = tlshd_quic_client_set_psk_session(conn);
+		tlshd_quic_client_set_psk_session(conn);
 		break;
 	default:
-		ret = -EINVAL;
 		tlshd_log_debug("Unrecognized auth mode (%d)", parms->auth_mode);
 	}
-	if (ret) {
-		conn->errcode = -ret;
+
+	if (!conn->session)
 		goto out;
-	}
 
 	tlshd_quic_start_handshake(conn);
-out:
 	parms->session_status = conn->errcode;
+out:
 	tlshd_quic_conn_destroy(conn);
 }
 #else
diff --git a/src/tlshd/server.c b/src/tlshd/server.c
index 6531f08..8bb769f 100644
--- a/src/tlshd/server.c
+++ b/src/tlshd/server.c
@@ -562,17 +562,17 @@ found:
 	return 0;
 }
 
-static int tlshd_quic_server_set_x509_session(struct tlshd_quic_conn *conn)
+static void tlshd_quic_server_set_x509_session(struct tlshd_quic_conn *conn)
 {
 	struct tlshd_handshake_parms *parms = conn->parms;
 	gnutls_certificate_credentials_t cred;
 	gnutls_datum_t ticket_key;
 	gnutls_session_t session;
-	int ret = -EINVAL;
+	int ret;
 
 	if (!tlshd_x509_server_get_certs(parms) || !tlshd_x509_server_get_privkey(parms)) {
-		tlshd_log_error("cert/privkey get error %d", -ret);
-		return ret;
+		tlshd_log_error("Failed to get cert or privkey");
+		return;
 	}
 
 	ret = gnutls_certificate_allocate_credentials(&cred);
@@ -619,7 +619,8 @@ static int tlshd_quic_server_set_x509_session(struct tlshd_quic_conn *conn)
 
 	conn->is_serv = 1;
 	conn->session = session;
-	return 0;
+	return;
+
 err_session:
 	gnutls_deinit(session);
 err_cred:
@@ -628,10 +629,9 @@ err:
 	tlshd_x509_server_put_privkey();
 	tlshd_x509_server_put_certs();
 	tlshd_log_gnutls_error(ret);
-	return ret;
 }
 
-static int tlshd_quic_server_set_psk_session(struct tlshd_quic_conn *conn)
+static void tlshd_quic_server_set_psk_session(struct tlshd_quic_conn *conn)
 {
 	gnutls_psk_server_credentials_t cred;
 	gnutls_session_t session;
@@ -654,14 +654,14 @@ static int tlshd_quic_server_set_psk_session(struct tlshd_quic_conn *conn)
 
 	conn->is_serv = 1;
 	conn->session = session;
-	return 0;
+	return;
+
 err_session:
 	gnutls_deinit(session);
 err_cred:
 	gnutls_psk_free_server_credentials(cred);
 err:
 	tlshd_log_gnutls_error(ret);
-	return ret;
 }
 
 /**
@@ -682,23 +682,20 @@ void tlshd_quic_serverhello_handshake(struct tlshd_handshake_parms *parms)
 
 	switch (parms->auth_mode) {
 	case HANDSHAKE_AUTH_X509:
-		ret = tlshd_quic_server_set_x509_session(conn);
+		tlshd_quic_server_set_x509_session(conn);
 		break;
 	case HANDSHAKE_AUTH_PSK:
-		ret = tlshd_quic_server_set_psk_session(conn);
+		tlshd_quic_server_set_psk_session(conn);
 		break;
 	default:
-		ret = -EINVAL;
 		tlshd_log_debug("Unrecognized auth mode (%d)", parms->auth_mode);
 	}
-	if (ret) {
-		conn->errcode = -ret;
+	if (!conn->session)
 		goto out;
-	}
 
 	tlshd_quic_start_handshake(conn);
-out:
 	parms->session_status = conn->errcode;
+out:
 	tlshd_quic_conn_destroy(conn);
 }
 #else
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake
  2025-09-25 16:38 [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake Xin Long
  2025-09-25 16:38 ` [PATCH 1/2] tlshd: leave session_status as EIO on GnuTLS failure in QUIC session setup Xin Long
@ 2025-09-25 16:38 ` Xin Long
  2025-09-26 13:14 ` [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors " Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Xin Long @ 2025-09-25 16:38 UTC (permalink / raw)
  To: kernel-tls-handshake; +Cc: Chuck Lever

Align QUIC handshake error handling with the TLS 1.3 path in
tlshd_start_tls_handshake(). In tlshd_quic_start_handshake(), any error
returned from the GnuTLS API is now logged and mapped to conn->errcode =
EACCES (session_status).

Note: unlike TLS 1.3, the QUIC handshake manages its own packet send/recv.
Timeouts are handled separately, with conn->errcode set to ETIMEDOUT
by quic_timer_handler().

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 src/tlshd/quic.c | 66 +++++++++++++++++++++++++++---------------------
 1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/src/tlshd/quic.c b/src/tlshd/quic.c
index f19e1db..0e0852e 100644
--- a/src/tlshd/quic.c
+++ b/src/tlshd/quic.c
@@ -188,7 +188,7 @@ static int quic_tp_send_func(gnutls_session_t session, gnutls_buffer_t extdata)
 	ret = gnutls_buffer_append_data(extdata, buf, len);
 	if (ret) {
 		tlshd_log_gnutls_error(ret);
-		return ret;
+		return -1;
 	}
 
 	return 0;
@@ -230,6 +230,7 @@ static char quic_priority[] =
 static int quic_session_set_priority(gnutls_session_t session, uint32_t cipher)
 {
 	char p[136] = {};
+	int ret;
 
 	memcpy(p, quic_priority, strlen(quic_priority));
 	switch (cipher) {
@@ -249,14 +250,19 @@ static int quic_session_set_priority(gnutls_session_t session, uint32_t cipher)
 		strcat(p, "AES-128-GCM:+AES-256-GCM:+AES-128-CCM:+CHACHA20-POLY1305");
 	}
 
-	return gnutls_priority_set_direct(session, p, NULL);
+	ret = gnutls_priority_set_direct(session, p, NULL);
+	if (ret) {
+		tlshd_log_gnutls_error(ret);
+		return -1;
+	}
+	return 0;
 }
 
 static int quic_session_set_alpns(gnutls_session_t session, char *alpn_data)
 {
 	gnutls_datum_t alpns[TLSHD_QUIC_MAX_ALPNS_LEN / 2];
 	char *alpn = strtok(alpn_data, ",");
-	int count = 0;
+	int count = 0, ret;
 
 	while (alpn) {
 		while (*alpn == ' ')
@@ -267,7 +273,12 @@ static int quic_session_set_alpns(gnutls_session_t session, char *alpn_data)
 		alpn = strtok(NULL, ",");
 	}
 
-	return gnutls_alpn_set_protocols(session, alpns, count, GNUTLS_ALPN_MANDATORY);
+	ret = gnutls_alpn_set_protocols(session, alpns, count, GNUTLS_ALPN_MANDATORY);
+	if (ret) {
+		tlshd_log_gnutls_error(ret);
+		return -1;
+	}
+	return 0;
 }
 
 static gnutls_record_encryption_level_t quic_get_encryption_level(uint8_t level)
@@ -401,7 +412,7 @@ static int quic_handshake_crypto_data(const struct tlshd_quic_conn *conn,
 	level = quic_get_encryption_level(level);
 	if (datalen > 0) {
 		ret = gnutls_handshake_write(session, level, data, datalen);
-		if (ret != 0) {
+		if (ret) {
 			if (!gnutls_error_is_fatal(ret))
 				return 0;
 			goto err;
@@ -418,7 +429,7 @@ static int quic_handshake_crypto_data(const struct tlshd_quic_conn *conn,
 err:
 	gnutls_alert_send_appropriate(session, ret);
 	tlshd_log_gnutls_error(ret);
-	return ret;
+	return -1;
 }
 
 /**
@@ -486,24 +497,25 @@ static int tlshd_quic_session_configure(struct tlshd_quic_conn *conn)
 	gnutls_session_t session = conn->session;
 	int ret;
 
-	ret = quic_session_set_priority(session, conn->cipher);
-	if (ret)
-		return ret;
+	if (quic_session_set_priority(session, conn->cipher))
+		return -1;
 
-	if (conn->alpns[0]) {
-		ret = quic_session_set_alpns(session, conn->alpns);
-		if (ret)
-			return ret;
-	}
+	if (conn->alpns[0] && quic_session_set_alpns(session, conn->alpns))
+		return -1;
 
 	gnutls_handshake_set_secret_function(session, quic_secret_func);
 	gnutls_handshake_set_read_function(session, quic_read_func);
 	gnutls_alert_set_read_function(session, quic_alert_read_func);
 
-	return gnutls_session_ext_register(
+	ret = gnutls_session_ext_register(
 		session, "QUIC Transport Parameters", QUIC_TLSEXT_TP_PARAM,
 		GNUTLS_EXT_TLS, quic_tp_recv_func, quic_tp_send_func, NULL, NULL, NULL,
 		GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_EE);
+	if (ret) {
+		tlshd_log_gnutls_error(ret);
+		return -1;
+	}
+	return 0;
 }
 
 static void tlshd_quic_recv_session_ticket(struct tlshd_quic_conn *conn)
@@ -532,16 +544,16 @@ static void tlshd_quic_recv_session_ticket(struct tlshd_quic_conn *conn)
 		return;
 
 	/* process new session ticket msg and get the generated session data */
-	ret = quic_handshake_crypto_data(conn, QUIC_CRYPTO_APP, conn->ticket, len);
-	if (ret) {
-		conn->errcode = -ret;
+	if (quic_handshake_crypto_data(conn, QUIC_CRYPTO_APP, conn->ticket, len)) {
+		conn->errcode = EACCES;
 		return;
 	}
+
 	size = sizeof(conn->ticket);
 	ret = gnutls_session_get_data(session, conn->ticket, &size);
 	if (ret) {
 		tlshd_log_gnutls_error(ret);
-		conn->errcode = -ret;
+		conn->errcode = EACCES;
 		return;
 	}
 
@@ -569,17 +581,14 @@ void tlshd_quic_start_handshake(struct tlshd_quic_conn *conn)
 	FD_ZERO(&readfds);
 	FD_SET(sockfd, &readfds);
 
-	ret = tlshd_quic_session_configure(conn);
-	if (ret) {
-		tlshd_log_gnutls_error(ret);
-		conn->errcode = -ret;
+	if (tlshd_quic_session_configure(conn)) {
+		conn->errcode = EACCES;
 		return;
 	}
 
 	if (!conn->is_serv) {
-		ret = quic_handshake_crypto_data(conn, QUIC_CRYPTO_INITIAL, NULL, 0);
-		if (ret) {
-			conn->errcode = -ret;
+		if (quic_handshake_crypto_data(conn, QUIC_CRYPTO_INITIAL, NULL, 0)) {
+			conn->errcode = EACCES;
 			return;
 		}
 
@@ -614,9 +623,8 @@ void tlshd_quic_start_handshake(struct tlshd_quic_conn *conn)
 				return tlshd_log_error("socket recvmsg error %d", errno);
 			}
 			tlshd_log_debug("> Handshake RECV: %u %u", msg->len, msg->level);
-			ret = quic_handshake_crypto_data(conn, msg->level, msg->data, msg->len);
-			if (ret) {
-				conn->errcode = -ret;
+			if (quic_handshake_crypto_data(conn, msg->level, msg->data, msg->len)) {
+				conn->errcode = EACCES;
 				return;
 			}
 		}
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake
  2025-09-25 16:38 [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake Xin Long
  2025-09-25 16:38 ` [PATCH 1/2] tlshd: leave session_status as EIO on GnuTLS failure in QUIC session setup Xin Long
  2025-09-25 16:38 ` [PATCH 2/2] tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake Xin Long
@ 2025-09-26 13:14 ` Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Chuck Lever @ 2025-09-26 13:14 UTC (permalink / raw)
  To: Xin Long, kernel-tls-handshake

On 9/25/25 9:38 AM, Xin Long wrote:
> This series aligns QUIC error handling in tlshd with the TLS 1.3 code.
> 
> - On GnuTLS failure during session setup, log the error and leave
>   parms session_status = EIO.
> 
> - On GnuTLS failure during handshake, log the error and set conn
>   errcode = EACCES.
> 
> Xin Long (2):
>   tlshd: leave session_status as EIO on GnuTLS failure in QUIC session
>     setup
>   tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake
> 
>  src/tlshd/client.c | 42 ++++++++++++++---------------
>  src/tlshd/quic.c   | 66 ++++++++++++++++++++++++++--------------------
>  src/tlshd/server.c | 29 +++++++++-----------
>  3 files changed, 70 insertions(+), 67 deletions(-)
> 

Thanks, these look great. I've folded them into the series to fix up
the Doxygen comments, and posted that for comments.

-- 
Chuck Lever

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-09-26 13:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-25 16:38 [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors in QUIC handshake Xin Long
2025-09-25 16:38 ` [PATCH 1/2] tlshd: leave session_status as EIO on GnuTLS failure in QUIC session setup Xin Long
2025-09-25 16:38 ` [PATCH 2/2] tlshd: set conn errcode to EACCES on GnuTLS failure in QUIC handshake Xin Long
2025-09-26 13:14 ` [PATCH 0/2] tlshd: do not set conn errcode to GnuTLS errors " Chuck Lever

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox