From: Wilfred Mallawa Test that outgoing plaintext records respect the tls record_size_limit set using setsockopt(). The record size 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 Signed-off-by: Wilfred Mallawa --- tools/testing/selftests/net/tls.c | 149 ++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index 0f5640d8dc7f..c5bd431d5af3 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -24,6 +24,7 @@ #include "../kselftest_harness.h" #define TLS_PAYLOAD_MAX_LEN 16384 +#define TLS_TX_RECORD_SIZE_LIM 5 #define SOL_TLS 282 static int fips_enabled; @@ -2770,6 +2771,154 @@ TEST_F(tls_err, poll_partial_rec_async) } } +/* + * Parse a stream of TLS records and ensure that each record respects + * the specified @record_size_limit. + */ +static size_t parse_tls_records(struct __test_metadata *_metadata, + const __u8 *rx_buf, int rx_len, int overhead, + __u16 record_size_limit) +{ + 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, record_size_limit); + rec += rec_header_len + record_payload_len; + } + + return total_plaintext_rx; +} + +TEST(tx_record_size) +{ + struct tls_crypto_info_keys tls12; + int cfd, ret, fd, rx_len, overhead; + size_t total_plaintext_rx = 0; + __u8 tx[1024], rx[2000]; + __u8 *rec; + __u16 limit = 128; + __u16 opt = 0; + __u8 rec_header_len = 5; + 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_RECORD_SIZE_LIM, &limit, sizeof(limit)); + ASSERT_EQ(ret, 0); + + ret = getsockopt(cfd, SOL_TLS, TLS_TX_RECORD_SIZE_LIM, &opt, &optlen); + ASSERT_EQ(ret, 0); + ASSERT_EQ(limit, opt); + ASSERT_EQ(optlen, sizeof(limit)); + + memset(tx, 0, sizeof(tx)); + EXPECT_EQ(send(cfd, tx, sizeof(tx), 0), sizeof(tx)); + close(cfd); + + ret = recv(fd, rx, sizeof(rx), 0); + memcpy(&rx_len, rx + 3, 2); + rx_len = htons(rx_len); + + /* + * 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(tx_record_size_open_rec) +{ + struct tls_crypto_info_keys tls12; + int cfd, ret, fd, rx_len, overhead; + size_t total_plaintext_rx = 0; + __u8 tx[1024], rx[2000]; + __u16 tx_partial = 256; + __u8 *rec; + __u16 og_limit = 512, limit = 128; + __u8 rec_header_len = 5; + 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_RECORD_SIZE_LIM, &og_limit, + sizeof(og_limit)); + ASSERT_EQ(ret, 0); + + memset(tx, 0, sizeof(tx)); + EXPECT_EQ(send(cfd, tx, tx_partial, MSG_MORE), tx_partial); + + /* + * Changing the record size limit with a pending open record should + * not be allowed. + */ + ret = setsockopt(cfd, SOL_TLS, TLS_TX_RECORD_SIZE_LIM, &limit, + sizeof(limit)); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EBUSY); + + EXPECT_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); + memcpy(&rx_len, rx + 3, 2); + rx_len = htons(rx_len); + + /* + * 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; -- 2.51.0