webrtc/net/dcsctp
Victor Boivie 63e273ad4b dcsctp: Persist all state in state cookie
In the example below, the association is being established between peer
A and Z, and A is the initiating party.

Before this CL, when an association was about to be established, Z would
after having received the INIT chunk, persist state in the socket about
which verification tag and initial TSN that was picked. These would be
re-generated on every incoming INIT (that's fine), but when A had
extracted the cookie from INIT_ACK and sent a reply (COOKIE_ECHO) with
the state cookie, that could fail validation when it's received by Z, if
the sent cookie was not the most recent one or if the COOKIE_ECHO had a
verification tag coming not from the most recent INIT_ACK, because Z had
replaced the state in the socket with the one generated when the second
INIT_ACK chunk was generated - state it used for validation of future
received data.

In other words:
A -> INIT 1
<timeout>
A -> INIT 2 (retransmission of INIT 1)
INIT 1 -> Z - sends INIT_ACK 1 with verification_tag=1, initial_tsn=1,
              cookie 1 (and records these to socket state)
INIT 2 -> Z - sends INIT_ACK 2 with verification_tag=2, initial_tsn=2,
              cookie 2 (replaces socket state with the new data)
INIT_ACK 1 -> A -> sends COOKIE_ECHO with verification_tag=1, cookie 1
COOKIE_ECHO (cookie 1) -> Z <FAILS, as the state isn't as expected>.

The solution is really to do what RFC4960 says, to not maintain any
state as the receiving peer until COOKIE_ECHO has been received. This
was initially not done because the underlying reason why this is
important in SCTP is to avoid denial of service, and this is why SCTP
has the four-way handshake. But for Data Channels - SCTP over DTLS -
this attack vector isn't available. So the implementation was
"simplified" by keeping socket state instead of encoding it in the
state cookie, but that obviously had downsides.

So with this CL, the non-initiating peer in connection establishment
doesn't keep any socket state, and puts all that state in the state
cookie instead. This allows any COOKIE_ECHO to be received by Z.

Bug: webrtc:15712
Change-Id: I596c7330ce27292612d3c9f86b21c712f6f4e408
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/330440
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41340}
2023-12-08 10:54:42 +00:00
..
common Move StrJoin to rtc_base/strings 2023-11-15 12:10:28 +00:00
fuzzers dcsctp: Convert use of TimeMs to webrtc::Timestamp 2023-11-12 21:12:29 +00:00
packet Move StrJoin to rtc_base/strings 2023-11-15 12:10:28 +00:00
public dcsctp: Convert use of TimeMs to webrtc::Timestamp 2023-11-12 21:12:29 +00:00
rx dcsctp: Remove deprecated delivery checks 2023-11-30 17:27:52 +00:00
socket dcsctp: Persist all state in state cookie 2023-12-08 10:54:42 +00:00
testing dcsctp: Rename message_id to mid 2023-10-05 18:48:21 +00:00
timer dcsctp: Convert use of TimeMs to webrtc::Timestamp 2023-11-12 21:12:29 +00:00
tx dcsctp: Rename outstanding bytes to unacked bytes 2023-12-04 19:10:17 +00:00
BUILD.gn dcsctp: Add socket fuzzer helper 2021-05-12 15:06:17 +00:00
OWNERS dcsctp: Add OWNERS file 2021-04-20 10:42:58 +00:00