mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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:
committed by
Jakub Kicinski
parent
82cb5be6ad
commit
5f30bc4706
@@ -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, ¬ls);
|
||||
|
||||
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, ¬ls);
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user