Skip to content

Commit 88d73b7

Browse files
committed
replace zero UDP checksum with 0xFFF to avoid receivers interpretingt it
as "no checksum was computer"
1 parent d665201 commit 88d73b7

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

src/test/unit/unit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ Suite *wolf_suite(void)
675675
tcase_add_test(tc_proto, test_regression_paws_rejects_stale_timestamp);
676676
tcase_add_test(tc_proto, test_regression_dhcp_nak_restarts_configuration);
677677
tcase_add_test(tc_proto, test_regression_dns_rcode_error_aborts_query);
678+
tcase_add_test(tc_proto, test_regression_udp_checksum_zero_substituted_with_ffff);
678679

679680
tcase_add_test(tc_utils, test_transport_checksum);
680681
tcase_add_test(tc_utils, test_iphdr_set_checksum);

src/test/unit/unit_tests_proto.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,4 +4317,52 @@ START_TEST(test_regression_dns_rcode_error_aborts_query)
43174317
END_TEST
43184318

43194319

4320+
/* RFC 768: if the computed UDP checksum is zero, it must be transmitted
4321+
* as 0xFFFF. A zero checksum means "no checksum computed" and the
4322+
* receiver would skip verification. The current code stores the raw
4323+
* transport_checksum result without zero-substitution. */
4324+
START_TEST(test_regression_udp_checksum_zero_substituted_with_ffff)
4325+
{
4326+
struct wolfIP s;
4327+
struct tsocket *ts;
4328+
struct wolfIP_udp_datagram udp;
4329+
4330+
/* Craft a UDP datagram whose pseudo-header + data sums to 0xFFFF
4331+
* in one's complement, causing transport_checksum to return 0.
4332+
*
4333+
* Pseudo-header: src=0, dst=0, proto=0x11, len=8
4334+
* sum = 0x0011 + 0x0008 = 0x0019
4335+
* UDP header: src_port=0xFFDE, dst_port=0, udp_len=8, csum=0
4336+
* sum += 0xFFDE + 0 + 0x0008 = 0xFFE6
4337+
* Total = 0x0019 + 0xFFE6 = 0xFFFF -> ~0xFFFF = 0 */
4338+
4339+
wolfIP_init(&s);
4340+
mock_link_init(&s);
4341+
wolfIP_ipconfig_set(&s, 0, 0, 0);
4342+
4343+
/* Set up a UDP socket so ip_output_add_header can be called */
4344+
ts = &s.udpsockets[0];
4345+
memset(ts, 0, sizeof(*ts));
4346+
ts->proto = WI_IPPROTO_UDP;
4347+
ts->S = &s;
4348+
ts->local_ip = 0;
4349+
ts->remote_ip = 0;
4350+
ts->if_idx = TEST_PRIMARY_IF;
4351+
4352+
memset(&udp, 0, sizeof(udp));
4353+
udp.src_port = ee16(0xFFDE);
4354+
udp.dst_port = 0;
4355+
udp.len = ee16(8);
4356+
udp.csum = 0;
4357+
4358+
ip_output_add_header(ts, (struct wolfIP_ip_packet *)&udp,
4359+
WI_IPPROTO_UDP, IP_HEADER_LEN + 8);
4360+
4361+
/* The stored checksum must be 0xFFFF, not 0. */
4362+
ck_assert_uint_ne(udp.csum, 0);
4363+
ck_assert_uint_eq(ee16(udp.csum), 0xFFFF);
4364+
}
4365+
END_TEST
4366+
4367+
43204368
/* ----------------------------------------------------------------------- */

src/wolfip.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3084,8 +3084,12 @@ static int ip_output_add_header(struct tsocket *t, struct wolfIP_ip_packet *ip,
30843084
tcp->csum = ee16(transport_checksum(&ph, &tcp->src_port));
30853085
} else if (proto == WI_IPPROTO_UDP) {
30863086
struct wolfIP_udp_datagram *udp = (struct wolfIP_udp_datagram *)ip;
3087+
uint16_t udp_csum;
30873088
udp->csum = 0;
3088-
udp->csum = ee16(transport_checksum(&ph, &udp->src_port));
3089+
udp_csum = transport_checksum(&ph, &udp->src_port);
3090+
/* RFC 768: a zero checksum means "no checksum computed," so
3091+
* a computed zero must be transmitted as 0xFFFF. */
3092+
udp->csum = ee16(udp_csum ? udp_csum : 0xFFFF);
30893093
} else if (proto == WI_IPPROTO_ICMP) {
30903094
struct wolfIP_icmp_packet *icmp = (struct wolfIP_icmp_packet *)ip;
30913095
icmp->csum = 0;

0 commit comments

Comments
 (0)