Skip to content

Commit c1610ed

Browse files
committed
tlshd: support setting the record size limit
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 fetches maximum support send size as specified by the record size limit extension or as defined in GnuTLS, this value is then passed to the kernel through setsockopt() using the new TLS_TX_MAX_PAYLOAD_LEN option, such that the kernel can ensure outgoing records do not exceed the size specified. The respective kernel changes are currently applied to net-next [2]. [1] https://www.rfc-editor.org/rfc/rfc8449#section-4 [2] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=82cb5be6ad64198a3a028aeb49dcc7f6224d558a Signed-off-by: Wilfred Mallawa <[email protected]>
1 parent c85d09d commit c1610ed

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

configure.ac

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ AC_CHECK_LIB([gnutls], [gnutls_get_system_config_file],
8585
AC_CHECK_LIB([gnutls], [gnutls_psk_allocate_client_credentials2],
8686
[AC_DEFINE([HAVE_GNUTLS_PSK_ALLOCATE_CREDENTIALS2], [1],
8787
[Define to 1 if you have the gnutls_psk_allocate_client_credentials2 function.])])
88+
AC_CHECK_LIB([gnutls], [gnutls_record_get_max_send_size],
89+
[AC_DEFINE([HAVE_GNUTLS_RECORD_GET_MAX_SEND_SIZE], [1],
90+
[Define to 1 if you have the gnutls_record_get_max_send_size function.])])
8891

8992
AC_MSG_CHECKING(for ML-DSA support in gnutls)
9093
AC_COMPILE_IFELSE(
@@ -97,6 +100,17 @@ if test "x$have_mldsa" = xyes ; then
97100
AC_DEFINE([HAVE_GNUTLS_MLDSA], [1], [Define to 1 if gnutls supports ML-DSA])
98101
fi
99102

103+
AC_MSG_CHECKING(for TLS_TX_MAX_PAYLOAD_LEN in linux/tls.h)
104+
AC_COMPILE_IFELSE(
105+
[AC_LANG_PROGRAM([[ #include <linux/tls.h> ]],
106+
[[ (void) TLS_TX_MAX_PAYLOAD_LEN; ]])],
107+
[ have_tls_tx_max_payload_len=yes ],
108+
[ have_tls_tx_max_payload_len=no ])
109+
AC_MSG_RESULT([$have_tls_tx_max_payload_len])
110+
if test "x$have_tls_tx_max_payload_len" = xyes ; then
111+
AC_DEFINE([HAVE_TLS_TX_MAX_PAYLOAD_LEN], [1], [Define to 1 if linux/tls.h defines TLS_TX_MAX_PAYLOAD_LEN])
112+
fi
113+
100114
AC_SUBST([AM_CPPFLAGS])
101115

102116
AC_CONFIG_FILES([Makefile \

src/tlshd/handshake.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <gnutls/abstract.h>
4444

4545
#include <glib.h>
46+
#include <linux/tls.h>
4647

4748
#include "tlshd.h"
4849
#include "netlink.h"

src/tlshd/ktls.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,26 @@ static bool tlshd_set_chacha20_poly1305_info(gnutls_session_t session, int sock,
347347
}
348348
#endif
349349

350+
#if defined(HAVE_GNUTLS_RECORD_GET_MAX_SEND_SIZE) && defined(HAVE_TLS_TX_MAX_PAYLOAD_LEN)
351+
static int tlshd_set_record_size(gnutls_session_t session)
352+
{
353+
uint16_t max_send_size;
354+
int ret;
355+
356+
max_send_size = gnutls_record_get_max_send_size(session);
357+
/* For TLS 1.3 kernel expects us to account for the ContentType */
358+
if (gnutls_protocol_get_version(session) == GNUTLS_TLS1_3)
359+
max_send_size -= 1;
360+
361+
ret = setsockopt(gnutls_transport_get_int(session), SOL_TLS,
362+
TLS_TX_MAX_PAYLOAD_LEN, &max_send_size, sizeof(max_send_size));
363+
if (ret < 0)
364+
tlshd_log_perror("setsockopt (TLS_TX_MAX_PAYLOAD_LEN)");
365+
366+
return ret;
367+
}
368+
#endif
369+
350370
/**
351371
* @brief Initialize a socket for use by kTLS
352372
* @param[in] session TLS session descriptor
@@ -363,6 +383,11 @@ unsigned int tlshd_initialize_ktls(gnutls_session_t session)
363383
return EIO;
364384
}
365385

386+
#if defined(HAVE_GNUTLS_RECORD_GET_MAX_SEND_SIZE) && defined(HAVE_TLS_TX_MAX_PAYLOAD_LEN)
387+
if (tlshd_set_record_size(session) < 0)
388+
return EIO;
389+
#endif
390+
366391
gnutls_transport_get_int2(session, &sockin, &sockout);
367392

368393
switch (gnutls_cipher_get(session)) {

0 commit comments

Comments
 (0)