Hi, TL;DR This is all about various aspects of how ACKs work in DTLS 1.3: - The DTLS 1.3 specification requires clarification regarding when ACKs should be sent. - Record-level ACKs make efficient implementations for IoT devices harder. I argue that handshake-level ACKs reduce implementation complexity and allow for optimized implementations.
Details: To illustrate, consider the following flight exchange, where the second and third message in the second flight get reordered: Client Server +----------+ | Seq No 1 |--------------------------> Received | Rec No a | +----------+ +---------------+ Received <------------------------| Seq No 1 | | Rec No b | +---------------+ +---------------+ +-------------| Seq No 2 | | | Rec No c | | +---------------+ | | +---------------+ Received <------------------------| Seq No 3 | | | Rec No d | | +---------------+ +-----------+ | | ACK |-------------------------> | RecNo ??? | | +-----------+ | | | | Received <----------+ The specification recommends that the client SHOULD send an ACK when it receives out-of-order handshake message - here message (3,d) while awaiting (2,c). However: Question: Which records does the client acknowledge in the ACK? This is in fact implementation-dependent: The client must only acknowledge record (3,d) if it has buffered it. Implementations which don't implement out of order buffering of handshake messages (to save RAM and ROM) must not acknowledge messages that weren't buffered. The reason is that otherwise the server is mislead in which messages need resending and which don't. Conclusion 1: If ACKs must only be sent for records which contain handshake messages which were actually fed into the flight buffering / reassembly module of the implementation, the specification should clearly say so. I consider this point to be prone to misinterpretation, potentially leading to incompatible implementations, because ACKs acknowledge receipt at record granularity, and yet they must be sent only under some assumptions on how their content was processed. Next, given that the generation of record-ACKs is therefore content-specific, I wonder why ACKs acknowledge records in the first place, and not triples of (handshake seq nr, fragment offset, fragment length). It appears to me that the latter matches their semantics much closer and allows for more simpler and more efficient implementations. I'll elaborate on that in the following. As I understand, the simplest implementation of the retransmission state machine using record-level ACKs works by buffering copies of records sent in a flight and retransmits those that don't get acknowledged. The record sequence numbers of the original and retransmitted records are internally associated with the opaque record content, so that ACKs for both the original and the retransmitted records can be recognized. In this approach, the record contents are opaque to the sender's retransmission state machine, which simplifies the implementation. However, it has major drawbacks: (1) It requires buffering the entire flight, which incurs high memory overhead that can be significant on constrained devices. Implementations should be allowed to not buffer handshake messages but re-generate them on the fly through a callback whenever retransmission is needed. Two examples: - Consider the Certificate message: The raw certificate (chain) must reside in RAM/ROM already, and the Certificate message could easily be re-regenerated from that. Buffering handshake messages instead creates significant and unnecessary overhead. - This is of increasing importance with the advent of post-quantum cryptography, which comes with significantly larger key material. (2) It doesn't allow switching the MTU for retransmission. Once the MTU may change for retransmission, the sender cannot keep track anymore of a single set of record sequence numbers per message such that an ACK for any of them confirms receipt of the message. Of course, no implementation is strictly _forced_ to follow the above approach, but the current record-level ACKs design significantly hardens any other approach: For example, retransmission through callbacks or support for MTU switching requires maintaining the tuples (record seq nr, lists of handshake fragments) for all transmissions of the last flight. (Note that, in particular, just remembering the mapping for the last transmission isn't enough, since an acknowledgement for an earlier transmission might arrive late.) The _sender_ would need to maintain less state, and would have an easier time figuring out what to retransmit, if ACKs acknowledged handshake fragments directly. On the _receiver_ side, there's no benefit of ACKing at the record level, either, because -- as we have just seen -- it is _not_ the case that it can be implemented as an automated mechanism at the record level, but needs to be triggered from the handshake layer, at a point where all information about the handshake content are available. Implementations following the above buffering-based approach don't increase in complexity through a switch to handshake level acknowledgements instead of record level acknowledgements: They can just treat the acknowledged handshake metadata as an _opaque_ identifier, replacing what was previously the record sequence number. Conclusion 2: Handshake-level ACKs simplify the retransmission state machine for non-buffering implementations on constrained devices, while not hardening buffering implementations using record-level ACKs so far. I'm aware of the lateness of this proposal, but would be happy if the group would discuss and consider handshake-level ACKs instead of record-level ACKs. Let me know what you think, Cheers, Hanno IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
_______________________________________________ TLS mailing list TLS@ietf.org https://www.ietf.org/mailman/listinfo/tls