selftests: tls: add tls record_size_limit test

Test that outgoing plaintext records respect the tls TLS_TX_MAX_PAYLOAD_LEN
set using setsockopt(). The limit is set to be 128, thus, in all received
records, the plaintext must not exceed this amount.

Also test that setting a new record size limit whilst a pending open
record exists is handled correctly by discarding the request.

Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20251022001937.20155-2-wilfred.opensource@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Wilfred Mallawa
2025-10-22 10:19:37 +10:00
committed by Jakub Kicinski
parent 82cb5be6ad
commit 5f30bc4706

View File

@@ -2856,6 +2856,147 @@ TEST_F(tls_err, oob_pressure)
EXPECT_EQ(send(self->fd2, buf, 5, MSG_OOB), 5);
}
/*
* Parse a stream of TLS records and ensure that each record respects
* the specified @max_payload_len.
*/
static size_t parse_tls_records(struct __test_metadata *_metadata,
const __u8 *rx_buf, int rx_len, int overhead,
__u16 max_payload_len)
{
const __u8 *rec = rx_buf;
size_t total_plaintext_rx = 0;
const __u8 rec_header_len = 5;
while (rec < rx_buf + rx_len) {
__u16 record_payload_len;
__u16 plaintext_len;
/* Sanity check that it's a TLS header for application data */
ASSERT_EQ(rec[0], 23);
ASSERT_EQ(rec[1], 0x3);
ASSERT_EQ(rec[2], 0x3);
memcpy(&record_payload_len, rec + 3, 2);
record_payload_len = ntohs(record_payload_len);
ASSERT_GE(record_payload_len, overhead);
plaintext_len = record_payload_len - overhead;
total_plaintext_rx += plaintext_len;
/* Plaintext must not exceed the specified limit */
ASSERT_LE(plaintext_len, max_payload_len);
rec += rec_header_len + record_payload_len;
}
return total_plaintext_rx;
}
TEST(tls_12_tx_max_payload_len)
{
struct tls_crypto_info_keys tls12;
int cfd, ret, fd, overhead;
size_t total_plaintext_rx = 0;
__u8 tx[1024], rx[2000];
__u16 limit = 128;
__u16 opt = 0;
unsigned int optlen = sizeof(opt);
bool notls;
tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_CCM_128,
&tls12, 0);
ulp_sock_pair(_metadata, &fd, &cfd, &notls);
if (notls)
exit(KSFT_SKIP);
/* Don't install keys on fd, we'll parse raw records */
ret = setsockopt(cfd, SOL_TLS, TLS_TX, &tls12, tls12.len);
ASSERT_EQ(ret, 0);
ret = setsockopt(cfd, SOL_TLS, TLS_TX_MAX_PAYLOAD_LEN, &limit,
sizeof(limit));
ASSERT_EQ(ret, 0);
ret = getsockopt(cfd, SOL_TLS, TLS_TX_MAX_PAYLOAD_LEN, &opt, &optlen);
EXPECT_EQ(ret, 0);
EXPECT_EQ(limit, opt);
EXPECT_EQ(optlen, sizeof(limit));
memset(tx, 0, sizeof(tx));
ASSERT_EQ(send(cfd, tx, sizeof(tx), 0), sizeof(tx));
close(cfd);
ret = recv(fd, rx, sizeof(rx), 0);
/*
* 16B tag + 8B IV -- record header (5B) is not counted but we'll
* need it to walk the record stream
*/
overhead = 16 + 8;
total_plaintext_rx = parse_tls_records(_metadata, rx, ret, overhead,
limit);
ASSERT_EQ(total_plaintext_rx, sizeof(tx));
close(fd);
}
TEST(tls_12_tx_max_payload_len_open_rec)
{
struct tls_crypto_info_keys tls12;
int cfd, ret, fd, overhead;
size_t total_plaintext_rx = 0;
__u8 tx[1024], rx[2000];
__u16 tx_partial = 256;
__u16 og_limit = 512, limit = 128;
bool notls;
tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_CCM_128,
&tls12, 0);
ulp_sock_pair(_metadata, &fd, &cfd, &notls);
if (notls)
exit(KSFT_SKIP);
/* Don't install keys on fd, we'll parse raw records */
ret = setsockopt(cfd, SOL_TLS, TLS_TX, &tls12, tls12.len);
ASSERT_EQ(ret, 0);
ret = setsockopt(cfd, SOL_TLS, TLS_TX_MAX_PAYLOAD_LEN, &og_limit,
sizeof(og_limit));
ASSERT_EQ(ret, 0);
memset(tx, 0, sizeof(tx));
ASSERT_EQ(send(cfd, tx, tx_partial, MSG_MORE), tx_partial);
/*
* Changing the payload limit with a pending open record should
* not be allowed.
*/
ret = setsockopt(cfd, SOL_TLS, TLS_TX_MAX_PAYLOAD_LEN, &limit,
sizeof(limit));
ASSERT_EQ(ret, -1);
ASSERT_EQ(errno, EBUSY);
ASSERT_EQ(send(cfd, tx + tx_partial, sizeof(tx) - tx_partial, MSG_EOR),
sizeof(tx) - tx_partial);
close(cfd);
ret = recv(fd, rx, sizeof(rx), 0);
/*
* 16B tag + 8B IV -- record header (5B) is not counted but we'll
* need it to walk the record stream
*/
overhead = 16 + 8;
total_plaintext_rx = parse_tls_records(_metadata, rx, ret, overhead,
og_limit);
ASSERT_EQ(total_plaintext_rx, sizeof(tx));
close(fd);
}
TEST(non_established) {
struct tls12_crypto_info_aes_gcm_256 tls12;
struct sockaddr_in addr;