Subject: [quicwg/base-drafts] Implicitly Acknowledging CRYTPO Data (#1741)

From: Nick Banks <[email-masked]>
Date: Wed, 12 Sep 2018 12:57:18 -0700

I recently hit an assert in my crypto TX path, and after looking at it for a while I figured out it was because it was trying to retransmit data with an older encryption key than the one currently configured for sending. I was starting to look into how to fix my code to allow this case, but then I was thinking more. Should I?

The actual packets exchanged were (from the server PoV):

```
[quic][RX][0] LH Ver:0xe0000ff DestCID:78e0d957a1d861c9 SrcCID:5d9b053011bce8f1 Type:I (Token 0 bytes) (Payload 1226 bytes) (PktNum 1 bytes)
[quic][RX][0]   CRYPTO Offset:0 Len:291
[quic][RX][0]   PADDING Len:914

[quic][TX][0] LH Ver:0xe0000ff DestCID:5d9b053011bce8f1 SrcCID:78444bb1394fce67 Type:I (Token 0 bytes) (Payload 182 bytes) (PktNum 1 bytes)
[quic][TX][0]   ACK Largest:0 Delay:856
[quic][TX][0]     0
[quic][TX][0]   CRYPTO Offset:0 Len:155
[quic][TX][1] LH Ver:0xe0000ff DestCID:5d9b053011bce8f1 SrcCID:78444bb1394fce67 Type:HS (Payload 1020 bytes) (PktNum 1 bytes)
[quic][TX][1]   CRYPTO Offset:0 Len:999
[quic][TX][2] LH Ver:0xe0000ff DestCID:5d9b053011bce8f1 SrcCID:78444bb1394fce67 Type:HS (Payload 1228 bytes) (PktNum 1 bytes)
[quic][TX][2]   CRYPTO Offset:999 Len:1206
[quic][TX][3] LH Ver:0xe0000ff DestCID:5d9b053011bce8f1 SrcCID:78444bb1394fce67 Type:HS (Payload 1228 bytes) (PktNum 1 bytes)
[quic][TX][3]   CRYPTO Offset:2205 Len:1206
[quic][TX][4] LH Ver:0xe0000ff DestCID:5d9b053011bce8f1 SrcCID:78444bb1394fce67 Type:HS (Payload 1209 bytes) (PktNum 1 bytes)
[quic][TX][4]   CRYPTO Offset:3411 Len:1187

[quic][RX][0] LH Ver:0xe0000ff DestCID:78444bb1394fce67 SrcCID:5d9b053011bce8f1 Type:HS (Payload 61 bytes) (PktNum 1 bytes)
[quic][RX][0]   CRYPTO Offset:0 Len:36
[quic][RX][0]   ACK Largest:4 Delay:0
[quic][RX][0]     1 - 4

[quic][TX][0] FACK 4
[quic][TX][0] retransmitting
```

So either the ACK for my server's Initial packet wasn't sent yet, was sent after the Handshake packet or was lost. Either way, I end up deciding it was lost and my generic packet loss detection/recovery logic kicks in and decided the data in packet 0 should be retransmitted.

The thing is, at the crypto (and TLS) layers I know I have received handshake data (all of it actually) and I am ready to send out my NST in 1-RTT. In order to get this far in the handshake, the peer MUST have received my Initial packet, so it would seem pointless to actually retransmit it. So should I?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741

---

From: MikkelFJ <[email-masked]>
Date: Wed, 12 Sep 2018 13:26:54 -0700

Generally I believe you should never transmit using anything but the latest key until multi-path has been invented. But that is after the handshake completes. Before that there are different crypto levels and the peer might not be able to proceed if data lands on the wrong level. If I remember correctly your impl. tries to map different crypto spaces into a single space and handle everything uniformly - but this is case where that isn't helpful. If the post handshake logic can completely ignore handshake issues, the general cases becomes simpler.

As to retransmitting packet 0 - the main concern is if a man in the middle box can trick you into believing that it did not drop the packet towards the intended endpoint. So you'd have to be conservative until you have certs verified. You also don't want to special case no-retransmission just because you can unless there are some important gains, but that is for packet 1+. Packet 0 is a special case, or so I would assume:

Packet 0 is in fact special because it cannot have frames that can be retransmitted in later packets because the initial connection ID is setting up the connection and must be transmitted as an exact copy, or transmitted as an entirely new connection attempt. Anything else probably messes with various reset / retry token mechanisms.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420785624

---

From: Nick Banks <[email-masked]>
Date: Wed, 12 Sep 2018 14:10:23 -0700

I'm not sure man in the middle argument is very helpful here, because if there is someone in the middle that already responded to my Initial with their own Handshake data (and TLS accepted it), then the connection is dead. Nothing the client can do or I can do now will recover that. That being said, if TLS accepted the client's Handshake data, and told me the connection is now complete, I'm fairly confident that there was no man in the middle.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420798892

---

From: MikkelFJ <[email-masked]>
Date: Wed, 12 Sep 2018 21:34:36 +0000 (UTC)

Well, yes, that is my point - you need to be conservative and not make that conclusion before it is safe to do so. Perhaps this is obvious from your initial post, but it would be easy to make the mistake that just because the (apparent) server responded with some packet, it must have seen packet 0.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420805714

---

From: MikkelFJ <[email-masked]>
Date: Wed, 12 Sep 2018 14:40:45 -0700

If you need to retransmit packet 0, the connection is not dead, it is just reset - you obviously have to forget any prior received data. But your point suggests that it may be wiser to initiate a new connection with a different packet 0 instead of reusing the original with all the potential confusion that could happen with proper or adversarial endpoints.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420807346

---

From: Rui Paulo <[email-masked]>
Date: Wed, 12 Sep 2018 15:30:06 -0700

Section 8.2 already says "or the crypto state machine implicitly knows that the peer received the data."

I think it's a valid performance optimization to flush initial packets from the retransmission queue when handshake keys have been derived and also to flush handshake packets when the 1rtt keys have been keys have been derived.  The spec doesn't seem to prevent this optimization.  If it's dangerous, then the spec should definitely prevent it. 

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420819424

---

From: Martin Thomson <[email-masked]>
Date: Wed, 12 Sep 2018 17:03:52 -0700

This is precisely the subject of discussion at the last IETF meeting.  It might help to review that.   What the implementation is doing here is valid: it operates loss detection on Initial packets independent of other packets.  To some extent, that's necessary.

That the handshake has proceeded and that activity at the next epoch indicates successful receipt of the necessary packets is extra information you aren't required to assimilate, but as @rpaulo says, you are free to do so.  We explicitly decided not to prohibit the optimization suggested, but nor do we require that anyone implement the optimization.  All THAT means is that you can't assume that the other side is going to stop sending you Initial+CRYPTO if you don't acknowledge it.

The exchange @nibanks describes is entirely valid as implemented, if suboptimal.  That's all.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420838259

---

From: Martin Thomson <[email-masked]>
Date: Wed, 12 Sep 2018 17:04:34 -0700

For the record, a discussion like this is probably better taken to the list.  It doesn't identify an issue (though it might imply one).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#issuecomment-420838376

---

From: Martin Thomson <[email-masked]>
Date: Wed, 12 Sep 2018 17:04:34 -0700

Closed #1741.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1741#event-1842446782