From 494238811ebc2c716224ba6beaaf9dff54b1d666 Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Fri, 4 Jul 2025 15:25:55 +1000 Subject: [PATCH] handshake: support record size limit extension RFC 8449 [1] Section 4 defines the record_size_limit TLS extension, which allows peers to negotiate a maximum plaintext record size during the TLS handshake. The value must be between 64 bytes and 16,384 bytes (2^14). If a TLS endpoint receives a record larger than its advertised limit, it must send a fatal record_overflow alert. This patch adds support for extracting the record size limit value from the gnutls session and passing it to the kernel. This is to be used by the kernel at the tls layer limit outgoing records to the maximum record size limit as specified by the endpoint. [1] https://www.rfc-editor.org/rfc/rfc8449#section-4 Signed-off-by: Wilfred Mallawa --- src/tlshd/handshake.c | 6 ++++++ src/tlshd/netlink.c | 7 +++++++ src/tlshd/netlink.h | 1 + src/tlshd/tlshd.h | 1 + 4 files changed, 15 insertions(+) diff --git a/src/tlshd/handshake.c b/src/tlshd/handshake.c index ed5c13b..2ebf959 100644 --- a/src/tlshd/handshake.c +++ b/src/tlshd/handshake.c @@ -80,6 +80,7 @@ static void tlshd_save_nagle(gnutls_session_t session, int *saved) void tlshd_start_tls_handshake(gnutls_session_t session, struct tlshd_handshake_parms *parms) { + ssize_t record_size_limit; int saved, ret; char *desc; @@ -112,6 +113,11 @@ void tlshd_start_tls_handshake(gnutls_session_t session, gnutls_free(desc); parms->session_status = tlshd_initialize_ktls(session); + record_size_limit = gnutls_record_get_record_size_limit(session); + if (record_size_limit <= 0) + tlshd_log_notice("Inavlid Record size limit: %zd\n", record_size_limit); + else + parms->record_size_limit = (uint32_t)record_size_limit; } /** diff --git a/src/tlshd/netlink.c b/src/tlshd/netlink.c index c08e5e5..9cd448b 100644 --- a/src/tlshd/netlink.c +++ b/src/tlshd/netlink.c @@ -376,6 +376,7 @@ static const struct tlshd_handshake_parms tlshd_default_handshake_parms = { .peerids = NULL, .remote_peerids = NULL, .msg_status = 0, + .record_size_limit = 0, .session_status = EIO, }; @@ -550,6 +551,12 @@ void tlshd_genl_done(struct tlshd_handshake_parms *parms) if (err < 0) goto out_free; + err = nla_put_u32(msg, HANDSHAKE_A_DONE_RECORD_SIZE_LIMIT, parms->record_size_limit); + if (err < 0) { + tlshd_log_nl_error("nla_put record_size_limit", err); + goto out_free; + } + sendit: if (tlshd_delay_done) { /* Undocumented tlshd.conf parameter: diff --git a/src/tlshd/netlink.h b/src/tlshd/netlink.h index 662e7de..645eeb7 100644 --- a/src/tlshd/netlink.h +++ b/src/tlshd/netlink.h @@ -55,6 +55,7 @@ enum { HANDSHAKE_A_DONE_STATUS = 1, HANDSHAKE_A_DONE_SOCKFD, HANDSHAKE_A_DONE_REMOTE_AUTH, + HANDSHAKE_A_DONE_RECORD_SIZE_LIMIT, __HANDSHAKE_A_DONE_MAX, HANDSHAKE_A_DONE_MAX = (__HANDSHAKE_A_DONE_MAX - 1) diff --git a/src/tlshd/tlshd.h b/src/tlshd/tlshd.h index a0dd47e..a9687b7 100644 --- a/src/tlshd/tlshd.h +++ b/src/tlshd/tlshd.h @@ -41,6 +41,7 @@ struct tlshd_handshake_parms { GArray *peerids; GArray *remote_peerids; int msg_status; + uint32_t record_size_limit; unsigned int session_status; };