Skip to content

Commit 4755619

Browse files
committed
Expose FreeRTOS+TCP checksum APIs to the firewall.
Signed-off-by: Hugo Lefeuvre <[email protected]> (cherry picked from commit af215ef)
1 parent 14aa581 commit 4755619

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

lib/tcpip/checksum-internal.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright SCI Semiconductor and CHERIoT Contributors.
2+
// SPDX-License-Identifier: MIT
3+
4+
#pragma once
5+
#include <compartment-macros.h>
6+
#include <stddef.h>
7+
#include <stdint.h>
8+
/**
9+
* Internal APIs that the TCP/IP compartment exposes for the firewall to use.
10+
*
11+
* These should be called only from the firewall compartment (validated by
12+
* checking the compartment linkage report). These APIs trust the caller and
13+
* do *not* check arguments.
14+
*/
15+
16+
/**
17+
* Returns the IPv4 checksum for passed packet.
18+
*
19+
* This function is stateless and can be called at any point of the lifetime of
20+
* the TCP/IP stack.
21+
*
22+
* The IPv4 header (only) should be passed in `ipv4Header`, along with its
23+
* length in `headerLength`.
24+
*
25+
* The returned checksum is in network byte order and can be used as-is for
26+
* transmission in the IPv4 header.
27+
*/
28+
uint16_t __cheri_compartment("TCPIP")
29+
network_calculate_ipv4_checksum(const uint8_t *ipv4Header,
30+
size_t headerLength);
31+
32+
/**
33+
* Returns the TCP checksum for passed packet.
34+
*
35+
* This function is stateless and can be called at any point of the lifetime of
36+
* the TCP/IP stack.
37+
*
38+
* Unlike `network_calculate_ipv4_checksum`, this takes the entire Ethernet
39+
* frame into `frame`, along with its length in `frameLength`.
40+
*
41+
* The offset of the TCP checksum in the `frame` buffer must be passed in
42+
* `tcpChecksumOffset`.
43+
*
44+
* The returned checksum is in network byte order and can be used as-is for
45+
* transmission in the TCP header.
46+
*/
47+
uint16_t __cheri_compartment("TCPIP")
48+
network_calculate_tcp_checksum(const uint8_t *frame,
49+
size_t frameLength,
50+
size_t tcpChecksumOffset);

lib/tcpip/network_wrapper.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <tcpip_error_handler.h>
88

99
#include "../firewall/firewall.hh"
10+
#include "checksum-internal.h"
1011
#include "network-internal.h"
1112
#include "tcpip-internal.h"
1213

@@ -472,6 +473,39 @@ namespace
472473
}
473474
} // namespace
474475

476+
uint16_t network_calculate_ipv4_checksum(const uint8_t *ipv4Header, size_t headerLength)
477+
{
478+
// Note: no restarting checks because stateless.
479+
480+
// `usGenerateChecksum` returns a checksum which is 1) not negated (we
481+
// must bitwise NOT it) and 2) in host byte order.
482+
return htons(~usGenerateChecksum(
483+
0 /* generate checksum for the full packet */, ipv4Header, headerLength));
484+
}
485+
486+
uint16_t network_calculate_tcp_checksum(const uint8_t *frame,
487+
size_t frameLength,
488+
size_t tcpChecksumOffset)
489+
{
490+
// Note: no restarting checks because stateless.
491+
492+
// `usGenerateProtocolChecksum` *writes* the checksum into the packet
493+
// buffer. It is not possible to have it return the checksum instead of
494+
// modifying the buffer. This is really annoying because we only have a
495+
// read-only capability to the frame, as we want to *return* the
496+
// checksum.
497+
//
498+
// To workaround this, make a local copy of the Ethernet frame and
499+
// extract the computed checksum from it using `tcpChecksumOffset`.
500+
// Putting this copy on the stack should be fine since this is only
501+
// used in RST packets which have no payload.
502+
uint8_t copy[frameLength];
503+
memcpy(copy, frame, frameLength);
504+
uint16_t *checksum = reinterpret_cast<uint16_t *>(&copy[tcpChecksumOffset]);
505+
usGenerateProtocolChecksum(copy, frameLength, true /* write checksum */);
506+
return *checksum;
507+
}
508+
475509
int network_host_resolve(const char *hostname,
476510
bool useIPv6,
477511
NetworkAddress *address)

0 commit comments

Comments
 (0)